[fixes] tooltip format, legend, labels, heatmap margin

This commit is contained in:
Prateeksha Singh 2018-03-06 03:05:40 +05:30
parent ded80791dd
commit 546ce96a12
21 changed files with 683 additions and 545 deletions

View File

@ -133,6 +133,9 @@ class SvgTip {
fill() {
let title;
if(this.index) {
this.container.setAttribute('data-point-index', this.index);
}
if(this.titleValueFirst) {
title = `<strong>${this.titleValue}</strong>${this.titleName}`;
} else {
@ -179,13 +182,14 @@ class SvgTip {
}
}
setValues(x, y, titleName = '', titleValue = '', listValues = [], titleValueFirst = 0) {
this.titleName = titleName;
this.titleValue = titleValue;
setValues(x, y, title = {}, listValues = [], index = -1) {
this.titleName = title.name;
this.titleValue = title.value;
this.listValues = listValues;
this.x = x;
this.y = y;
this.titleValueFirst = titleValueFirst;
this.titleValueFirst = title.valueFirst || 0;
this.index = index;
this.refresh();
}
@ -202,7 +206,7 @@ class SvgTip {
}
}
const VERT_SPACE_OUTSIDE_BASE_CHART = 40;
const VERT_SPACE_OUTSIDE_BASE_CHART = 50;
const TRANSLATE_Y_BASE_CHART = 20;
const LEFT_MARGIN_BASE_CHART = 60;
const RIGHT_MARGIN_BASE_CHART = 40;
@ -220,7 +224,7 @@ const MIN_BAR_PERCENT_HEIGHT = 0.01;
const LINE_CHART_DOT_SIZE = 4;
const DOT_OVERLAY_SIZE_INCR = 4;
const DEFAULT_CHAR_WIDTH = 8;
const DEFAULT_CHAR_WIDTH = 7;
// Universal constants
const ANGLE_RATIO = Math.PI / 180;
@ -574,7 +578,7 @@ function makeVertLine(x, label, y1, y2, options={}) {
dy: FONT_SIZE + 'px',
'font-size': FONT_SIZE + 'px',
'text-anchor': 'middle',
innerHTML: label
innerHTML: label + ""
});
let line = createSVG('g', {
@ -729,7 +733,7 @@ function yRegion(y1, y2, width, label) {
let labelSvg = createSVG('text', {
className: 'chart-label',
x: width - getStringWidth(label, 4.5) - LABEL_MARGIN,
x: width - getStringWidth(label+"", 4.5) - LABEL_MARGIN,
y: 0,
dy: (FONT_SIZE / -2) + 'px',
'font-size': FONT_SIZE + 'px',
@ -761,6 +765,8 @@ function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={})
height: height || meta.minHeight // TODO: correct y for positive min height
});
label += "";
if(!label && !label.length) {
return rect;
} else {
@ -777,6 +783,7 @@ function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={})
});
let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})`
});
group.appendChild(rect);
@ -795,6 +802,8 @@ function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
r: radius
});
label += "";
if(!label && !label.length) {
return dot;
} else {
@ -812,6 +821,7 @@ function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
});
let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})`
});
group.appendChild(dot);
@ -873,9 +883,10 @@ let makeOverlay = {
}
let overlay = unit.cloneNode();
let radius = unit.getAttribute('r');
overlay.setAttribute('r', radius + DOT_OVERLAY_SIZE_INCR);
overlay.style.fill = '#000000';
overlay.style.opacity = '0.4';
let fill = unit.getAttribute('fill');
overlay.setAttribute('r', parseInt(radius) + DOT_OVERLAY_SIZE_INCR);
overlay.setAttribute('fill', fill);
overlay.style.opacity = '0.6';
if(transformValue) {
overlay.setAttribute('transform', transformValue);
@ -1266,7 +1277,10 @@ class BaseChart {
setTimeout(() => {this.update();}, this.initTimeout);
}
this.renderLegend();
if(!onlyWidthChange) {
this.renderLegend();
}
this.setupNavigation(init);
}
@ -1456,10 +1470,11 @@ class AggregationChart extends BaseChart {
renderLegend() {
let s = this.state;
this.statsWrapper.textContent = '';
this.legendTotals = s.sliceTotals.slice(0, this.config.maxLegendPoints);
let x_values = this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels : s.labels;
let xValues = s.labels;
this.legendTotals.map((d, i) => {
if(d) {
let stats = $.create('div', {
@ -1468,7 +1483,7 @@ class AggregationChart extends BaseChart {
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
<span class="text-muted">${x_values[i]}:</span>
<span class="text-muted">${xValues[i]}:</span>
${d}
</span>`;
}
@ -1542,7 +1557,7 @@ class PercentageChart extends AggregationChart {
? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%");
this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip();
}
});
@ -2008,7 +2023,7 @@ class PieChart extends AggregationChart {
return {
sliceStrings: s.sliceStrings,
colors: this.colors
}
};
}.bind(this)
]
];
@ -2038,7 +2053,7 @@ class PieChart extends AggregationChart {
let title = (this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels[i] : this.state.labels[i]) + ': ';
let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%");
this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip();
} else {
transform(path,'translate3d(0,0,0)');
@ -2106,8 +2121,6 @@ function addDays(date, numberOfDays) {
date.setDate(date.getDate() + numberOfDays);
}
// export function getMonthName() {}
function normalize(x) {
// Calculates mantissa and exponent of a number
// Returns normalized number and exponent
@ -2328,15 +2341,15 @@ class Heatmap extends BaseChart {
this.domain = options.domain || '';
this.subdomain = options.subdomain || '';
this.data = options.data || {};
this.discrete_domains = options.discrete_domains || 1;
this.count_label = options.count_label || '';
this.discreteDomains = options.discreteDomains === 0 ? 0 : 1;
this.countLabel = options.countLabel || '';
let today = new Date();
this.start = options.start || addDays(today, 365);
let legend_colors = (options.legend_colors || []).slice(0, 5);
this.legend_colors = this.validate_colors(legend_colors)
? legend_colors
let legendColors = (options.legendColors || []).slice(0, 5);
this.legendColors = this.validate_colors(legendColors)
? legendColors
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
// Fixed 5-color theme,
@ -2347,6 +2360,12 @@ class Heatmap extends BaseChart {
this.setup();
}
setMargins() {
super.setMargins();
this.leftMargin = 10;
this.translateY = 10;
}
validate_colors(colors) {
if(colors.length < 5) return 0;
@ -2369,21 +2388,21 @@ class Heatmap extends BaseChart {
this.start = new Date();
this.start.setFullYear( this.start.getFullYear() - 1 );
}
this.first_week_start = new Date(this.start.toDateString());
this.last_week_start = new Date(this.today.toDateString());
if(this.first_week_start.getDay() !== 7) {
addDays(this.first_week_start, (-1) * this.first_week_start.getDay());
this.firstWeekStart = new Date(this.start.toDateString());
this.lastWeekStart = new Date(this.today.toDateString());
if(this.firstWeekStart.getDay() !== 7) {
addDays(this.firstWeekStart, (-1) * this.firstWeekStart.getDay());
}
if(this.last_week_start.getDay() !== 7) {
addDays(this.last_week_start, (-1) * this.last_week_start.getDay());
if(this.lastWeekStart.getDay() !== 7) {
addDays(this.lastWeekStart, (-1) * this.lastWeekStart.getDay());
}
this.no_of_cols = getWeeksBetween(this.first_week_start + '', this.last_week_start + '') + 1;
this.no_of_cols = getWeeksBetween(this.firstWeekStart + '', this.lastWeekStart + '') + 1;
}
calcWidth() {
this.baseWidth = (this.no_of_cols + 3) * 12 ;
if(this.discrete_domains) {
if(this.discreteDomains) {
this.baseWidth += (12 * 12);
}
}
@ -2397,21 +2416,20 @@ class Heatmap extends BaseChart {
'data-groups',
`translate(0, 20)`
);
// Array.prototype.slice.call(
// this.container.querySelectorAll('.graph-stats-container, .sub-title, .title')
// ).map(d => {
// d.style.display = 'None';
// });
// this.chartWrapper.style.marginTop = '0px';
// this.chartWrapper.style.paddingTop = '0px';
this.container.querySelector('.title').style.display = 'None';
this.container.querySelector('.sub-title').style.display = 'None';
this.container.querySelector('.graph-stats-container').style.display = 'None';
this.chartWrapper.style.marginTop = '0px';
this.chartWrapper.style.paddingTop = '0px';
}
calc() {
let data_values = Object.keys(this.data).map(key => this.data[key]);
this.distribution = calcDistribution(data_values, this.distribution_size);
let dataValues = Object.keys(this.data).map(key => this.data[key]);
this.distribution = calcDistribution(dataValues, this.distribution_size);
this.month_names = ["January", "February", "March", "April", "May", "June",
this.monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
}
@ -2425,118 +2443,118 @@ class Heatmap extends BaseChart {
this.domainLabelGroup.textContent = '';
this.dataGroups.textContent = '';
let current_week_sunday = new Date(this.first_week_start);
this.week_col = 0;
this.current_month = current_week_sunday.getMonth();
let currentWeekSunday = new Date(this.firstWeekStart);
this.weekCol = 0;
this.currentMonth = currentWeekSunday.getMonth();
this.months = [this.current_month + ''];
this.month_weeks = {}, this.month_start_points = [];
this.month_weeks[this.current_month] = 0;
this.month_start_points.push(13);
this.months = [this.currentMonth + ''];
this.monthWeeks = {}, this.monthStartPoints = [];
this.monthWeeks[this.currentMonth] = 0;
this.monthStartPoints.push(13);
for(var i = 0; i < no_of_weeks; i++) {
let data_group, month_change = 0;
let day = new Date(current_week_sunday);
let dataGroup, monthChange = 0;
let day = new Date(currentWeekSunday);
[data_group, month_change] = this.get_week_squares_group(day, this.week_col);
this.dataGroups.appendChild(data_group);
this.week_col += 1 + parseInt(this.discrete_domains && month_change);
this.month_weeks[this.current_month]++;
if(month_change) {
this.current_month = (this.current_month + 1) % 12;
this.months.push(this.current_month + '');
this.month_weeks[this.current_month] = 1;
[dataGroup, monthChange] = this.get_week_squares_group(day, this.weekCol);
this.dataGroups.appendChild(dataGroup);
this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
this.monthWeeks[this.currentMonth]++;
if(monthChange) {
this.currentMonth = (this.currentMonth + 1) % 12;
this.months.push(this.currentMonth + '');
this.monthWeeks[this.currentMonth] = 1;
}
addDays(current_week_sunday, 7);
addDays(currentWeekSunday, 7);
}
this.render_month_labels();
}
get_week_squares_group(current_date, index) {
const no_of_weekdays = 7;
const square_side = 10;
const cell_padding = 2;
get_week_squares_group(currentDate, index) {
const noOfWeekdays = 7;
const squareSide = 10;
const cellPadding = 2;
const step = 1;
const today_time = this.today.getTime();
const todayTime = this.today.getTime();
let month_change = 0;
let week_col_change = 0;
let monthChange = 0;
let weekColChange = 0;
let data_group = makeSVGGroup(this.dataGroups, 'data-group');
let dataGroup = makeSVGGroup(this.dataGroups, 'data-group');
for(var y = 0, i = 0; i < no_of_weekdays; i += step, y += (square_side + cell_padding)) {
let data_value = 0;
for(var y = 0, i = 0; i < noOfWeekdays; i += step, y += (squareSide + cellPadding)) {
let dataValue = 0;
let colorIndex = 0;
let current_timestamp = current_date.getTime()/1000;
let timestamp = Math.floor(current_timestamp - (current_timestamp % 86400)).toFixed(1);
let currentTimestamp = currentDate.getTime()/1000;
let timestamp = Math.floor(currentTimestamp - (currentTimestamp % 86400)).toFixed(1);
if(this.data[timestamp]) {
data_value = this.data[timestamp];
dataValue = this.data[timestamp];
}
if(this.data[Math.round(timestamp)]) {
data_value = this.data[Math.round(timestamp)];
dataValue = this.data[Math.round(timestamp)];
}
if(data_value) {
colorIndex = getMaxCheckpoint(data_value, this.distribution);
if(dataValue) {
colorIndex = getMaxCheckpoint(dataValue, this.distribution);
}
let x = 13 + (index + week_col_change) * 12;
let x = 13 + (index + weekColChange) * 12;
let dataAttr = {
'data-date': getDdMmYyyy(current_date),
'data-value': data_value,
'data-day': current_date.getDay()
'data-date': getDdMmYyyy(currentDate),
'data-value': dataValue,
'data-day': currentDate.getDay()
};
let heatSquare = makeHeatSquare('day', x, y, square_side,
this.legend_colors[colorIndex], dataAttr);
let heatSquare = makeHeatSquare('day', x, y, squareSide,
this.legendColors[colorIndex], dataAttr);
data_group.appendChild(heatSquare);
dataGroup.appendChild(heatSquare);
let next_date = new Date(current_date);
addDays(next_date, 1);
if(next_date.getTime() > today_time) break;
let nextDate = new Date(currentDate);
addDays(nextDate, 1);
if(nextDate.getTime() > todayTime) break;
if(next_date.getMonth() - current_date.getMonth()) {
month_change = 1;
if(this.discrete_domains) {
week_col_change = 1;
if(nextDate.getMonth() - currentDate.getMonth()) {
monthChange = 1;
if(this.discreteDomains) {
weekColChange = 1;
}
this.month_start_points.push(13 + (index + week_col_change) * 12);
this.monthStartPoints.push(13 + (index + weekColChange) * 12);
}
current_date = next_date;
currentDate = nextDate;
}
return [data_group, month_change];
return [dataGroup, monthChange];
}
render_month_labels() {
// this.first_month_label = 1;
// if (this.first_week_start.getDate() > 8) {
// if (this.firstWeekStart.getDate() > 8) {
// this.first_month_label = 0;
// }
// this.last_month_label = 1;
// let first_month = this.months.shift();
// let first_month_start = this.month_start_points.shift();
// let first_month_start = this.monthStartPoints.shift();
// render first month if
// let last_month = this.months.pop();
// let last_month_start = this.month_start_points.pop();
// let last_month_start = this.monthStartPoints.pop();
// render last month if
this.months.shift();
this.month_start_points.shift();
this.monthStartPoints.shift();
this.months.pop();
this.month_start_points.pop();
this.monthStartPoints.pop();
this.month_start_points.map((start, i) => {
let month_name = this.month_names[this.months[i]].substring(0, 3);
this.monthStartPoints.map((start, i) => {
let month_name = this.monthNames[this.months[i]].substring(0, 3);
let text = makeText('y-value-text', start+12, 10, month_name);
this.domainLabelGroup.appendChild(text);
});
@ -2548,19 +2566,19 @@ class Heatmap extends BaseChart {
).map(el => {
el.addEventListener('mouseenter', (e) => {
let count = e.target.getAttribute('data-value');
let date_parts = e.target.getAttribute('data-date').split('-');
let dateParts = e.target.getAttribute('data-date').split('-');
let month = this.month_names[parseInt(date_parts[1])-1].substring(0, 3);
let month = this.monthNames[parseInt(dateParts[1])-1].substring(0, 3);
let g_off = this.chartWrapper.getBoundingClientRect(), p_off = e.target.getBoundingClientRect();
let gOff = this.chartWrapper.getBoundingClientRect(), pOff = e.target.getBoundingClientRect();
let width = parseInt(e.target.getAttribute('width'));
let x = p_off.left - g_off.left + (width+2)/2;
let y = p_off.top - g_off.top - (width+2)/2;
let value = count + ' ' + this.count_label;
let name = ' on ' + month + ' ' + date_parts[0] + ', ' + date_parts[2];
let x = pOff.left - gOff.left + (width+2)/2;
let y = pOff.top - gOff.top - (width+2)/2;
let value = count + ' ' + this.countLabel;
let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
this.tip.setValues(x, y, name, value, [], 1);
this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
this.tip.showTip();
});
});
@ -2714,7 +2732,7 @@ class AxisChart extends BaseChart {
this.config.xAxisMode = args.axisOptions.xAxisMode || 'span';
this.config.yAxisMode = args.axisOptions.yAxisMode || 'span';
this.config.xIsSeries = args.axisOptions.xIsSeries || 1;
this.config.xIsSeries = args.axisOptions.xIsSeries || 0;
this.config.formatTooltipX = args.tooltipOptions.formatTooltipX;
this.config.formatTooltipY = args.tooltipOptions.formatTooltipY;
@ -2810,7 +2828,7 @@ class AxisChart extends BaseChart {
return;
}
s.yExtremes = new Array(s.datasetLength).fill(9999);
s.datasets.map((d, i) => {
s.datasets.map(d => {
d.yPositions.map((pos, j) => {
if(pos < s.yExtremes[j]) {
s.yExtremes[j] = pos;
@ -2824,9 +2842,9 @@ class AxisChart extends BaseChart {
if(this.data.yMarkers) {
this.state.yMarkers = this.data.yMarkers.map(d => {
d.position = scale(d.value, s.yAxis);
if(!d.label.includes(':')) {
d.label += ': ' + d.value;
}
// if(!d.label.includes(':')) {
// d.label += ': ' + d.value;
// }
return d;
});
}
@ -2928,7 +2946,7 @@ class AxisChart extends BaseChart {
}
let labels = new Array(s.datasetLength).fill('');
if(this.valuesOverPoints) {
if(this.config.valuesOverPoints) {
if(stacked && d.index === s.datasets.length - 1) {
labels = d.cumulativeYs;
} else {
@ -3037,12 +3055,15 @@ class AxisChart extends BaseChart {
let s = this.state;
if(!s.yExtremes) return;
let formatY = this.config.formatTooltipY;
let formatX = this.config.formatTooltipX;
let titles = s.xAxis.labels;
if(this.formatTooltipX && this.formatTooltipX(titles[0])) {
titles = titles.map(d=>this.formatTooltipX(d));
if(formatX && formatX(titles[0])) {
titles = titles.map(d=>formatX(d));
}
let formatY = this.formatTooltipY && this.formatTooltipY(this.y[0].values[0]);
formatY = formatY && formatY(s.yAxis.labels[0]) ? formatY : 0;
for(var i=s.datasetLength - 1; i >= 0 ; i--) {
let xVal = s.xAxis.positions[i];
@ -3053,19 +3074,37 @@ class AxisChart extends BaseChart {
let values = this.data.datasets.map((set, j) => {
return {
title: set.title,
value: formatY ? this.formatTooltipY(set.values[i]) : set.values[i],
title: set.name,
value: formatY ? formatY(set.values[i]) : set.values[i],
color: this.colors[j],
};
});
this.tip.setValues(x, y, titles[i], '', values);
this.tip.setValues(x, y, {name: titles[i], value: ''}, values, i);
this.tip.showTip();
break;
}
}
}
renderLegend() {
let s = this.data;
this.statsWrapper.textContent = '';
if(s.datasets.length > 1) {
s.datasets.map((d, i) => {
let stats = $.create('div', {
className: 'stats',
inside: this.statsWrapper
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
${d.name}
</span>`;
});
}
}
makeOverlay() {
if(this.overlayGuides) {
this.overlayGuides.forEach(g => {
@ -3079,7 +3118,7 @@ class AxisChart extends BaseChart {
type: c.unitType,
overlay: undefined,
units: c.units,
}
};
});
if(this.state.currentIndex === undefined) {
@ -3105,19 +3144,26 @@ class AxisChart extends BaseChart {
}
bindOverlay() {
// on event, update overlay
this.parent.addEventListener('data-select', (e) => {
this.parent.addEventListener('data-select', () => {
this.updateOverlay();
});
}
bindUnits(units_array) {
// units_array.map(unit => {
// unit.addEventListener('click', () => {
// let index = unit.getAttribute('data-point-index');
// this.setCurrentDataPoint(index);
// });
// });
bindUnits() {
this.dataUnitComponents.map(c => {
c.units.map(unit => {
unit.addEventListener('click', () => {
let index = unit.getAttribute('data-point-index');
this.setCurrentDataPoint(index);
});
});
});
// Note: Doesn't work as tooltip is absolutely positioned
this.tip.container.addEventListener('click', () => {
let index = this.tip.container.getAttribute('data-point-index');
this.setCurrentDataPoint(index);
});
}
updateOverlay() {
@ -3136,16 +3182,12 @@ class AxisChart extends BaseChart {
}
getDataPoint(index=this.state.currentIndex) {
// check for length
let s = this.state;
let data_point = {
index: index
index: index,
label: s.xAxis.labels[index],
values: s.datasets.map(d => d.values[index])
};
// let y = this.y[0];
// ['svg_units', 'yUnitPositions', 'values'].map(key => {
// let data_key = key.slice(0, key.length-1);
// data_point[data_key] = y[key][index];
// });
// data_point.label = this.xAxis.labels[index];
return data_point;
}
@ -3186,7 +3228,14 @@ class AxisChart extends BaseChart {
// addDataset(dataset, index) {}
// removeDataset(index = 0) {}
// updateDatasets(datasets) {}
updateDatasets(datasets) {
this.data.datasets.map((d, i) => {
if(datasets[i]) {
d.values = datasets[i];
}
});
this.update(this.data);
}
// updateDataPoint(dataPoint, index = 0) {}
// addDataPoint(dataPoint, index = 0) {}

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .graph-focus-margin{margin:0 5%}.chart-container>.title{margin-top:25px;margin-left:25px;text-align:left;font-weight:400;font-size:12px;color:#6c7680}.chart-container .graphics{margin-top:10px;padding-top:10px;padding-bottom:10px;position:relative}.chart-container .graph-stats-group{-ms-flex-pack:distribute;-webkit-box-flex:1;-ms-flex:1;flex:1}.chart-container .graph-stats-container,.chart-container .graph-stats-group{display:-webkit-box;display:-ms-flexbox;display:flex;justify-content:space-around}.chart-container .graph-stats-container{-ms-flex-pack:distribute;padding-top:10px}.chart-container .graph-stats-container .stats{padding-bottom:15px}.chart-container .graph-stats-container .stats-title{color:#8d99a6}.chart-container .graph-stats-container .stats-value{font-size:20px;font-weight:300}.chart-container .graph-stats-container .stats-description{font-size:12px;color:#8d99a6}.chart-container .graph-stats-container .graph-data .stats-value{color:#98d85b}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .percentage-graph .progress{margin-bottom:0}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path,.chart-container .multiaxis-chart .line-horizontal,.chart-container .multiaxis-chart .y-axis-guide{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}.chart-container .indicator,.chart-container .indicator-right{background:none;font-size:12px;vertical-align:middle;font-weight:700;color:#6c7680}.chart-container .indicator i{content:"";display:inline-block;height:8px;width:8px;border-radius:8px}.chart-container .indicator:before,.chart-container .indicator i{margin:0 4px 0 0}.chart-container .indicator-right:after{margin:0 0 0 4px}
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .graph-focus-margin{margin:0 5%}.chart-container>.title{margin-top:25px;margin-left:25px;text-align:left;font-weight:400;font-size:12px;color:#6c7680}.chart-container .graphics{margin-top:10px;padding-top:10px;padding-bottom:10px;position:relative}.chart-container .graph-stats-group{display:-webkit-box;display:-ms-flexbox;display:flex;-ms-flex-pack:distribute;justify-content:space-around;-webkit-box-flex:1;-ms-flex:1;flex:1}.chart-container .graph-stats-container{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between;padding:10px}.chart-container .graph-stats-container:after,.chart-container .graph-stats-container:before{content:"";display:block}.chart-container .graph-stats-container .stats{padding-bottom:15px}.chart-container .graph-stats-container .stats-title{color:#8d99a6}.chart-container .graph-stats-container .stats-value{font-size:20px;font-weight:300}.chart-container .graph-stats-container .stats-description{font-size:12px;color:#8d99a6}.chart-container .graph-stats-container .graph-data .stats-value{color:#98d85b}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .percentage-graph .progress{margin-bottom:0}.chart-container .dataset-units circle{stroke:#fff;stroke-width:2}.chart-container .dataset-units path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container .dataset-path,.chart-container .multiaxis-chart .line-horizontal,.chart-container .multiaxis-chart .y-axis-guide{stroke-width:2px}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}.chart-container .indicator,.chart-container .indicator-right{background:none;font-size:12px;vertical-align:middle;font-weight:700;color:#6c7680}.chart-container .indicator i{content:"";display:inline-block;height:8px;width:8px;border-radius:8px}.chart-container .indicator:before,.chart-container .indicator i{margin:0 4px 0 0}.chart-container .indicator-right:after{margin:0 0 0 4px}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,76 +1,100 @@
// Composite Chart
// ================================================================================
let report_count_list = [17, 40, 33, 44, 126, 156,
324, 333, 478, 495, 527];
let reportCountList = [152, 222, 199, 287, 534, 709,
1179, 1256, 1632, 1856, 1850];
let bar_composite_data = {
let lineCompositeData = {
labels: ["2007", "2008", "2009", "2010", "2011", "2012",
"2013", "2014", "2015", "2016", "2017"],
yMarkers: [
{
label: "Marker 1",
value: 420,
},
{
label: "Marker 2",
value: 250,
label: "Average 100 reports/month",
value: 1200,
}
],
yRegions: [
{
label: "Region Y 1",
start: 100,
end: 300
},
],
datasets: [{
"name": "Events",
"values": report_count_list,
// "formatted": report_count_list.map(d => d + " reports")
"values": reportCountList
}]
};
let line_composite_data = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [{
"values": [37, 36, 32, 33, 12, 34, 52, 45, 58, 57, 64, 35],
// "values": [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 40, 40],
// "values": [-36, -46, -45, -32, -27, -31, -30, -36, -39, -49, -40, -40],
}]
};
let more_line_data = [
[4, 0, 3, 1, 1, 2, 1, 2, 1, 0, 1, 1],
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[2, 3, 3, 2, 1, 4, 0, 1, 2, 7, 11, 4],
[7, 7, 2, 4, 0, 1, 5, 3, 1, 2, 0, 1],
[0, 2, 6, 2, 2, 1, 2, 3, 6, 3, 7, 10],
[9, 10, 8, 10, 6, 5, 8, 8, 24, 15, 10, 13],
[9, 13, 16, 9, 4, 5, 7, 10, 14, 22, 23, 24],
[20, 22, 28, 19, 28, 19, 14, 19, 51, 37, 29, 38],
[29, 20, 22, 16, 16, 19, 24, 26, 57, 31, 46, 27],
[36, 24, 38, 27, 15, 22, 24, 38, 32, 57, 139, 26],
[37, 36, 32, 33, 12, 34, 52, 45, 58, 57, 64, 35],
[36, 46, 45, 32, 27, 31, 30, 36, 39, 58, 82, 62],
// [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 40, 40]
// [-36, -46, -45, -32, -27, -31, -30, -36, -39, -49, -40, -40]
let fireball_5_25 = [
[4, 0, 3, 1, 1, 2, 1, 1, 1, 0, 1, 1],
[2, 3, 3, 2, 1, 3, 0, 1, 2, 7, 10, 4],
[5, 6, 2, 4, 0, 1, 4, 3, 0, 2, 0, 1],
[0, 2, 6, 2, 1, 1, 2, 3, 6, 3, 7, 8],
[6, 8, 7, 7, 4, 5, 6, 5, 22, 12, 10, 11],
[7, 10, 11, 7, 3, 2, 7, 7, 11, 15, 22, 20],
[13, 16, 21, 18, 19, 17, 12, 17, 31, 28, 25, 29],
[24, 14, 21, 14, 11, 15, 19, 21, 41, 22, 32, 18],
[31, 20, 30, 22, 14, 17, 21, 35, 27, 50, 117, 24],
[32, 24, 21, 27, 11, 27, 43, 37, 44, 40, 48, 32],
[31, 38, 36, 26, 23, 23, 25, 29, 26, 47, 61, 50],
];
let fireball_2_5 = [
[22, 6, 6, 9, 7, 8, 6, 14, 19, 10, 8, 20],
[11, 13, 12, 8, 9, 11, 9, 13, 10, 22, 40, 24],
[20, 13, 13, 19, 13, 10, 14, 13, 20, 18, 5, 9],
[7, 13, 16, 19, 12, 11, 21, 27, 27, 24, 33, 33],
[38, 25, 28, 22, 31, 21, 35, 42, 37, 32, 46, 53],
[50, 33, 36, 34, 35, 28, 27, 52, 58, 59, 75, 69],
[54, 67, 67, 45, 66, 51, 38, 64, 90, 113, 116, 87],
[84, 52, 56, 51, 55, 46, 50, 87, 114, 83, 152, 93],
[73, 58, 59, 63, 56, 51, 83, 140, 103, 115, 265, 89],
[106, 95, 94, 71, 77, 75, 99, 136, 129, 154, 168, 156],
[81, 102, 95, 72, 58, 91, 89, 122, 124, 135, 183, 171],
];
let fireballOver25 = [
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0],
[1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 2],
[3, 2, 1, 3, 2, 0, 2, 2, 2, 3, 0, 1],
[2, 3, 5, 2, 1, 3, 0, 2, 3, 5, 1, 4],
[7, 4, 6, 1, 9, 2, 2, 2, 20, 9, 4, 9],
[5, 6, 1, 2, 5, 4, 5, 5, 16, 9, 14, 9],
[5, 4, 7, 5, 1, 5, 3, 3, 5, 7, 22, 2],
[5, 13, 11, 6, 1, 7, 9, 8, 14, 17, 16, 3],
[8, 9, 8, 6, 4, 8, 5, 6, 14, 11, 21, 12]
];
let monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"];
let barCompositeData = {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [
{
name: "Over 25 reports",
values: fireballOver25[9],
},
{
name: "5 to 25 reports",
values: fireball_5_25[9],
},
{
name: "2 to 5 reports",
values: fireball_2_5[9]
}
]
};
let c1 = document.querySelector("#chart-composite-1");
let c2 = document.querySelector("#chart-composite-2");
let bar_composite_chart = new Chart (c1, {
let lineCompositeChart = new Chart (c1, {
title: "Fireball/Bolide Events - Yearly (reported)",
data: bar_composite_data,
data: lineCompositeData,
type: 'line',
height: 180,
height: 190,
colors: ['green'],
isNavigable: 1,
isSeries: 1,
// valuesOverPoints: 1,
valuesOverPoints: 1,
lineOptions: {
dotSize: 8
@ -79,25 +103,33 @@ let bar_composite_chart = new Chart (c1, {
// regionFill: 1
});
let line_composite_chart = new Chart (c2, {
data: line_composite_data,
let barCompositeChart = new Chart (c2, {
data: barCompositeData,
type: 'bar',
height: 180,
colors: ['#46a9f9'],
height: 190,
colors: ['violet', 'light-blue', '#46a9f9'],
isSeries: 1,
valuesOverPoints: 1,
xAxisMode: 'tick'
axisOptions: {
xAxisMode: 'tick'
},
barOptions: {
stacked: 1
},
});
bar_composite_chart.parent.addEventListener('data-select', (e) => {
line_composite_chart.updateDataset(more_line_data[e.index]);
lineCompositeChart.parent.addEventListener('data-select', (e) => {
let i = e.index;
barCompositeChart.updateDatasets([
fireballOver25[i], fireball_5_25[i], fireball_2_5[i]
]);
});
// Demo Chart (bar, linepts, scatter(blobs), percentage)
// ================================================================================
let type_data = {
let typeData = {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"],
@ -166,15 +198,13 @@ let type_data = {
]
};
let type_chart = new Chart("#chart-types", {
// title: "My Awesome Chart",
data: type_data,
let typeChart = new Chart("#chart-types", {
title: "My Awesome Chart",
data: typeData,
type: 'bar',
height: 250,
colors: ['purple', 'magenta', 'light-blue'],
isSeries: 1,
xAxisMode: 'tick',
yAxisMode: 'span',
valuesOverPoints: 1,
// maxLegendPoints: 6,
// maxSlices: 3,
@ -184,86 +214,45 @@ let type_chart = new Chart("#chart-types", {
},
tooltipOptions: {
formatTooltipX: d => (d + '').toUpperCase(),
formatTooltipY: d => d + ' pts'
formatTooltipY: d => d + ' pts',
}
});
Array.prototype.slice.call(
document.querySelectorAll('.chart-type-buttons button')
).map(el => {
el.addEventListener('click', (e) => {
let btn = e.target;
let type = btn.getAttribute('data-type');
let newChart = type_chart.getDifferentChart(type);
if(newChart){
type_chart = newChart;
}
Array.prototype.slice.call(
btn.parentNode.querySelectorAll('button')).map(el => {
el.classList.remove('active');
});
btn.classList.add('active');
});
});
// Trends Chart
// Aggregation chart
// ================================================================================
let trends_data = {
labels: [1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976,
1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986,
1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016] ,
datasets: [
{
"values": [132.9, 150.0, 149.4, 148.0, 94.4, 97.6, 54.1, 49.2, 22.5, 18.4,
39.3, 131.0, 220.1, 218.9, 198.9, 162.4, 91.0, 60.5, 20.6, 14.8,
33.9, 123.0, 211.1, 191.8, 203.3, 133.0, 76.1, 44.9, 25.1, 11.6,
28.9, 88.3, 136.3, 173.9, 170.4, 163.6, 99.3, 65.3, 45.8, 24.7,
12.6, 4.2, 4.8, 24.9, 80.8, 84.5, 94.0, 113.3, 69.8, 39.8]
}
]
};
let plotChartArgs = {
title: "Mean Total Sunspot Count - Yearly",
data: trends_data,
type: 'line',
let aggrChart = new Chart("#chart-aggr", {
data: typeData,
type: 'pie',
height: 250,
colors: ['blue'],
colors: ['purple', 'magenta', 'light-blue'],
isSeries: 1,
lineOptions: {
hideDots: 1,
heatline: 1,
},
axisOptions: {
xAxisMode: 'tick',
yAxisMode: 'span',
xIsSeries: 1
}
};
new Chart("#chart-trends", plotChartArgs);
maxLegendPoints: 6,
maxSlices: 10,
barOptions: {
stacked: 1
},
tooltipOptions: {
formatTooltipX: d => (d + '').toUpperCase(),
formatTooltipY: d => d + ' pts',
}
});
Array.prototype.slice.call(
document.querySelectorAll('.chart-plot-buttons button')
document.querySelectorAll('.aggr-type-buttons button')
).map(el => {
el.addEventListener('click', (e) => {
let btn = e.target;
let type = btn.getAttribute('data-type');
let config = {};
config[type] = 1;
if(['regionFill', 'heatline'].includes(type)) {
config.hideDots = 1;
let newChart = aggrChart.getDifferentChart(type);
if(newChart){
aggrChart = newChart;
}
// plotChartArgs.init = false;
plotChartArgs.lineOptions = config;
new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call(
btn.parentNode.querySelectorAll('button')).map(el => {
el.classList.remove('active');
@ -337,6 +326,71 @@ chart_update_buttons.querySelector('[data-update="remove"]').addEventListener("c
update_chart.removeDataPoint();
});
// Trends Chart
// ================================================================================
let trends_data = {
labels: [1967, 1968, 1969, 1970, 1971, 1972, 1973, 1974, 1975, 1976,
1977, 1978, 1979, 1980, 1981, 1982, 1983, 1984, 1985, 1986,
1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996,
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016] ,
datasets: [
{
values: [132.9, 150.0, 149.4, 148.0, 94.4, 97.6, 54.1, 49.2, 22.5, 18.4,
39.3, 131.0, 220.1, 218.9, 198.9, 162.4, 91.0, 60.5, 20.6, 14.8,
33.9, 123.0, 211.1, 191.8, 203.3, 133.0, 76.1, 44.9, 25.1, 11.6,
28.9, 88.3, 136.3, 173.9, 170.4, 163.6, 99.3, 65.3, 45.8, 24.7,
12.6, 4.2, 4.8, 24.9, 80.8, 84.5, 94.0, 113.3, 69.8, 39.8]
}
]
};
let plotChartArgs = {
title: "Mean Total Sunspot Count - Yearly",
data: trends_data,
type: 'line',
height: 250,
colors: ['blue'],
isSeries: 1,
lineOptions: {
hideDots: 1,
heatline: 1,
},
axisOptions: {
xAxisMode: 'tick',
yAxisMode: 'span',
xIsSeries: 1
}
};
new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call(
document.querySelectorAll('.chart-plot-buttons button')
).map(el => {
el.addEventListener('click', (e) => {
let btn = e.target;
let type = btn.getAttribute('data-type');
let config = {};
config[type] = 1;
if(['regionFill', 'heatline'].includes(type)) {
config.hideDots = 1;
}
// plotChartArgs.init = false;
plotChartArgs.lineOptions = config;
new Chart("#chart-trends", plotChartArgs);
Array.prototype.slice.call(
btn.parentNode.querySelectorAll('button')).map(el => {
el.classList.remove('active');
});
btn.classList.add('active');
});
});
// Event chart
// ================================================================================
@ -398,28 +452,24 @@ events_chart.parent.addEventListener('data-select', (e) => {
data_div.querySelector('img').src = "./assets/img/" + name.toLowerCase() + ".jpg";
});
// Aggregation chart
// ================================================================================
// Heatmap
// ================================================================================
let heatmap_data = {};
let heatmapData = {};
let current_date = new Date();
let timestamp = current_date.getTime()/1000;
timestamp = Math.floor(timestamp - (timestamp % 86400)).toFixed(1); // convert to midnight
for (var i = 0; i< 375; i++) {
heatmap_data[parseInt(timestamp)] = Math.floor(Math.random() * 5);
heatmapData[parseInt(timestamp)] = Math.floor(Math.random() * 5);
timestamp = Math.floor(timestamp - 86400).toFixed(1);
}
new Chart("#chart-heatmap", {
data: heatmap_data,
data: heatmapData,
type: 'heatmap',
legend_scale: [0, 1, 2, 4, 5],
legendScale: [0, 1, 2, 4, 5],
height: 115,
discrete_domains: 1
discreteDomains: 1
});
Array.prototype.slice.call(
@ -428,10 +478,10 @@ Array.prototype.slice.call(
el.addEventListener('click', (e) => {
let btn = e.target;
let mode = btn.getAttribute('data-mode');
let discrete_domains = 0;
let discreteDomains = 0;
if(mode === 'discrete') {
discrete_domains = 1;
discreteDomains = 1;
}
let colors = [];
@ -443,12 +493,12 @@ Array.prototype.slice.call(
}
new Chart("#chart-heatmap", {
data: heatmap_data,
data: heatmapData,
type: 'heatmap',
legend_scale: [0, 1, 2, 4, 5],
legendScale: [0, 1, 2, 4, 5],
height: 115,
discrete_domains: discrete_domains,
legend_colors: colors
discreteDomains: discreteDomains,
legendColors: colors
});
Array.prototype.slice.call(
@ -471,22 +521,22 @@ Array.prototype.slice.call(
colors = ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'];
}
let discrete_domains = 1;
let discreteDomains = 1;
let view_mode = document
.querySelector('.heatmap-mode-buttons .active')
.getAttribute('data-mode');
if(view_mode === 'continuous') {
discrete_domains = 0;
discreteDomains = 0;
}
new Chart("#chart-heatmap", {
data: heatmap_data,
data: heatmapData,
type: 'heatmap',
legend_scale: [0, 1, 2, 4, 5],
legendScale: [0, 1, 2, 4, 5],
height: 115,
discrete_domains: discrete_domains,
legend_colors: colors
discreteDomains: discreteDomains,
legendColors: colors
});
Array.prototype.slice.call(

View File

@ -44,67 +44,51 @@
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">
<!--Bars, Lines or <a href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts" target="_blank">Percentages</a>-->
Create a chart
</h6>
<p class="step-explain">Install</p>
<pre><code class="hljs console"> npm install frappe-charts</code></pre>
<p class="step-explain">And include it in your project</p>
<pre><code class="hljs javascript"> import Chart from "frappe-charts/dist/frappe-charts.min.esm"</code></pre>
<p class="step-explain">... or include it directly in your HTML</p>
<pre><code class="hljs html"> &lt;script src="https://unpkg.com/frappe-charts@0.0.8/dist/frappe-charts.min.iife.js"&gt;&lt;/script&gt;</code></pre>
<p class="step-explain">Make a new Chart</p>
<h6 class="margin-vertical-rem">Create a chart</h6>
<pre><code class="hljs html"> &lt!--HTML--&gt;
&lt;div id="chart"&gt;&lt;/div&gt;</code></pre>
<pre><code class="hljs javascript"> // Javascript
let data = {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
let chart = new Chart( "#chart", { // or DOM element
data: {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"],
datasets: [
{
label: "Some Data",
values: [25, 40, 30, 35, 8, 52, 17, -4]
},
{
label: "Another Set",
values: [25, 50, -10, 15, 18, 32, 27, 14]
},
{
label: "Yet Another",
values: [15, 20, -3, -15, 58, 12, -17, 37]
}
]
};
datasets: [
{
label: "Some Data", type: 'bar',
values: [25, 40, 30, 35, 8, 52, 17, -4]
},
{
label: "Another Set", type: 'bar',
values: [25, 50, -10, 15, 18, 32, 27, 14]
},
{
label: "Yet Another", type: 'line',
values: [15, 20, -3, -15, 58, 12, -17, 37]
}
]
},
let chart = new Chart({
parent: "#chart", // or a DOM element
title: "My Awesome Chart",
data: data,
type: 'bar', // or 'line', 'scatter', 'pie', 'percentage'
type: 'axis-mixed', // or 'bar', 'line', 'pie', 'percentage'
height: 250,
colors: ['#7cd6fd', 'violet', 'blue'],
// hex-codes or these preset colors;
// defaults (in order):
// ['light-blue', 'blue', 'violet', 'red',
// 'orange', 'yellow', 'green', 'light-green',
// 'purple', 'magenta', 'grey', 'dark-grey']
format_tooltip_x: d => (d + '').toUpperCase(),
format_tooltip_y: d => d + ' pts'
colors: ['#7cd6fd', 'violet', 'blue']
});</code></pre>
<div id="chart-types" class="border"></div>
<div class="btn-group chart-type-buttons margin-vertical-px mx-auto" role="group">
<!-- <div class="btn-group chart-type-buttons margin-vertical-px mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary active" data-type='bar'>Bar Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='line'>Line Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='pie'>Pie Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
</div> -->
<div id="chart-aggr" class="border"></div>
<div class="btn-group aggr-type-buttons margin-vertical-px mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary active" data-type='pie'>Pie Chart</button>
<button type="button" class="btn btn-sm btn-secondary" data-type='percentage'>Percentage Chart</button>
</div>
<p class="text-muted">
<!-- <p class="text-muted">
<a target="_blank" href="http://www.storytellingwithdata.com/blog/2011/07/death-to-pie-charts">Why Percentage?</a>
</p>
</p> -->
</div>
</div>
@ -113,42 +97,12 @@
<h6 class="margin-vertical-rem">
Update Values
</h6>
<pre><code class="hljs javascript"> // Update entire datasets
chart.updateData(
[
{values: new_dataset_1_values},
{values: new_dataset_2_values}
],
new_labels
);
// Add a new data point
chart.add_data_point(
[new_value_1, new_value_2],
new_label,
index // defaults to last index
);
// Remove a data point
chart.remove_data_point(index);</code></pre>
<div id="chart-update" class="border"></div>
<div class="chart-update-buttons mt-1 mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary" data-update="random">Random Data</button>
<button type="button" class="btn btn-sm btn-secondary" data-update="add">Add Value</button>
<button type="button" class="btn btn-sm btn-secondary" data-update="remove">Remove Value</button>
</div>
<pre><code class="hljs javascript margin-vertical-px"> ...
// Include specific Y values in input data to be displayed as lines
// (before passing data to a new chart):
data.specific_values = [
{
label: "Altitude",
line_type: "dashed", // or "solid"
value: 38
}
]
...</code></pre>
</div>
</div>
@ -157,12 +111,6 @@
<h6 class="margin-vertical-rem">
Plot Trends
</h6>
<pre><code class="hljs javascript"> ...
xAxisMode: 'tick', // for short label ticks
// or 'span' for long spanning vertical axis lines
yAxisMode: 'span', // for long horizontal lines, or 'tick'
isSeries: 1, // to allow for skipping of X values
...</code></pre>
<div id="chart-trends" class="border"></div>
<div class="btn-group chart-plot-buttons mt-1 mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary" data-type="hideDots">Line</button>
@ -170,13 +118,13 @@
<button type="button" class="btn btn-sm btn-secondary active" data-type="heatline">HeatLine</button>
<button type="button" class="btn btn-sm btn-secondary" data-type="regionFill">Region</button>
</div>
<pre><code class="hljs javascript margin-vertical-px"> ...
type: 'line', // Line Chart specific properties:
<!-- <pre><code class="hljs javascript margin-vertical-px"> ...
lineOptions: 'line', // Line Chart specific properties:
hideDots: 1, // Hide data points on the line; default 0
heatline: 1, // Show a value-wise line gradient; default 0
regionFill: 1, // Fill the area under the graph; default 0
...</code></pre>
...</code></pre> -->
</div>
</div>
@ -204,8 +152,7 @@
</div>
</div>
<pre><code class="hljs javascript margin-vertical-px"> ...
type: 'bar', // Bar Chart specific properties:
isNavigable: 1, // Navigate across bars; default 0
isNavigable: 1, // Navigate across data points; default 0
...
chart.parent.addEventListener('data-select', (e) => {
@ -214,22 +161,6 @@
</div>
</div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">
Simple Aggregations
</h6>
<div id="chart-aggr" class="border"></div>
<div class="chart-aggr-buttons mt-1 mx-auto" role="group">
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="sums">Show Sums</button>
<button type="button" class="btn btn-sm btn-secondary" data-aggregation="average">Show Averages</button>
</div>
<pre><code class="hljs javascript margin-vertical-px"> chart.show_sums(); // and `hide_sums()`
chart.show_averages(); // and `hide_averages()`</code></pre>
</div>
</div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">
@ -249,16 +180,16 @@
parent: "#heatmap",
type: 'heatmap',
height: 115,
data: heatmap_data, // object with date/timestamp-value pairs
data: heatmapData, // object with date/timestamp-value pairs
discrete_domains: 1 // default: 0
discreteDomains: 1 // default: 0
start: start_date,
start: startDate,
// A Date object;
// default: today's date in past year
// for an annual heatmap
legend_colors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'],
legendColors: ['#ebedf0', '#fdf436', '#ffc700', '#ff9100', '#06001c'],
// Set of five incremental colors,
// beginning with a low-saturation color for zero data;
// default: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127']
@ -267,6 +198,54 @@
</div>
</div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">All available options:</h6>
<pre><code class="hljs javascript"> // Javascript
let data = {
labels: ["12am-3am", "3am-6am", "6am-9am", "9am-12pm",
"12pm-3pm", "3pm-6pm", "6pm-9pm", "9pm-12am"],
datasets: [
{
label: "Some Data", type: 'bar',
values: [25, 40, 30, 35, 8, 52, 17, -4]
},
{
label: "Another Set", type: 'bar',
values: [25, 50, -10, 15, 18, 32, 27, 14]
},
{
label: "Yet Another", type: 'line',
values: [15, 20, -3, -15, 58, 12, -17, 37]
}
]
};
let chart = new Chart( "#chart", { // or DOM element
title: "My Awesome Chart",
data: data,
type: 'axis-mixed', // or 'bar', 'line', 'pie', 'percentage'
height: 250,
colors: ['#7cd6fd', 'violet', 'blue']
});</code></pre>
</div>
</div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<h6 class="margin-vertical-rem">Install</h6>
<p class="step-explain">Install via npm</p>
<pre><code class="hljs console"> npm install frappe-charts</code></pre>
<p class="step-explain">And include it in your project</p>
<pre><code class="hljs javascript"> import Chart from "frappe-charts/dist/frappe-charts.min.esm"</code></pre>
<p class="step-explain">... or include it directly in your HTML</p>
<pre><code class="hljs html"> &lt;script src="https://unpkg.com/frappe-charts@0.0.8/dist/frappe-charts.min.iife.js"&gt;&lt;/script&gt;</code></pre>
</div>
</div>
<div class="col-sm-10 push-sm-1">
<div class="dashboard-section">
<!-- Closing -->

View File

@ -50,10 +50,11 @@ export default class AggregationChart extends BaseChart {
renderLegend() {
let s = this.state;
this.statsWrapper.textContent = '';
this.legendTotals = s.sliceTotals.slice(0, this.config.maxLegendPoints);
let x_values = this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels : s.labels;
let xValues = s.labels;
this.legendTotals.map((d, i) => {
if(d) {
let stats = $.create('div', {
@ -62,7 +63,7 @@ export default class AggregationChart extends BaseChart {
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
<span class="text-muted">${x_values[i]}:</span>
<span class="text-muted">${xValues[i]}:</span>
${d}
</span>`;
}

View File

@ -2,11 +2,11 @@ import BaseChart from './BaseChart';
import { dataPrep, zeroDataPrep, getShortenedLabels } from '../utils/axis-chart-utils';
import { Y_AXIS_MARGIN } from '../utils/constants';
import { getComponent } from '../objects/ChartComponents';
import { getOffset, fire } from '../utils/dom';
import { $, getOffset, fire } from '../utils/dom';
import { calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex, scale } from '../utils/intervals';
import { floatTwo } from '../utils/helpers';
import { makeOverlay, updateOverlay } from '../utils/draw';
import { MIN_BAR_PERCENT_HEIGHT, DEFAULT_AXIS_CHART_TYPE, BAR_CHART_SPACE_RATIO, LINE_CHART_DOT_SIZE } from '../utils/constants';
import { MIN_BAR_PERCENT_HEIGHT, BAR_CHART_SPACE_RATIO, LINE_CHART_DOT_SIZE } from '../utils/constants';
export default class AxisChart extends BaseChart {
constructor(parent, args) {
@ -28,7 +28,7 @@ export default class AxisChart extends BaseChart {
this.config.xAxisMode = args.axisOptions.xAxisMode || 'span';
this.config.yAxisMode = args.axisOptions.yAxisMode || 'span';
this.config.xIsSeries = args.axisOptions.xIsSeries || 1;
this.config.xIsSeries = args.axisOptions.xIsSeries || 0;
this.config.formatTooltipX = args.tooltipOptions.formatTooltipX;
this.config.formatTooltipY = args.tooltipOptions.formatTooltipY;
@ -88,7 +88,7 @@ export default class AxisChart extends BaseChart {
positions: yPts.map(d => zeroLine - d * scaleMultiplier),
scaleMultiplier: scaleMultiplier,
zeroLine: zeroLine,
}
};
// Dependent if above changes
this.calcDatasetPoints();
@ -124,7 +124,7 @@ export default class AxisChart extends BaseChart {
return;
}
s.yExtremes = new Array(s.datasetLength).fill(9999);
s.datasets.map((d, i) => {
s.datasets.map(d => {
d.yPositions.map((pos, j) => {
if(pos < s.yExtremes[j]) {
s.yExtremes[j] = pos;
@ -138,9 +138,9 @@ export default class AxisChart extends BaseChart {
if(this.data.yMarkers) {
this.state.yMarkers = this.data.yMarkers.map(d => {
d.position = scale(d.value, s.yAxis);
if(!d.label.includes(':')) {
d.label += ': ' + d.value;
}
// if(!d.label.includes(':')) {
// d.label += ': ' + d.value;
// }
return d;
});
}
@ -170,7 +170,6 @@ export default class AxisChart extends BaseChart {
}
setupComponents() {
let s = this.state;
let componentConfigs = [
[
'yAxis',
@ -243,7 +242,7 @@ export default class AxisChart extends BaseChart {
}
let labels = new Array(s.datasetLength).fill('');
if(this.valuesOverPoints) {
if(this.config.valuesOverPoints) {
if(stacked && d.index === s.datasets.length - 1) {
labels = d.cumulativeYs;
} else {
@ -352,12 +351,15 @@ export default class AxisChart extends BaseChart {
let s = this.state;
if(!s.yExtremes) return;
let formatY = this.config.formatTooltipY;
let formatX = this.config.formatTooltipX;
let titles = s.xAxis.labels;
if(this.formatTooltipX && this.formatTooltipX(titles[0])) {
titles = titles.map(d=>this.formatTooltipX(d));
if(formatX && formatX(titles[0])) {
titles = titles.map(d=>formatX(d));
}
let formatY = this.formatTooltipY && this.formatTooltipY(this.y[0].values[0]);
formatY = formatY && formatY(s.yAxis.labels[0]) ? formatY : 0;
for(var i=s.datasetLength - 1; i >= 0 ; i--) {
let xVal = s.xAxis.positions[i];
@ -368,19 +370,37 @@ export default class AxisChart extends BaseChart {
let values = this.data.datasets.map((set, j) => {
return {
title: set.title,
value: formatY ? this.formatTooltipY(set.values[i]) : set.values[i],
title: set.name,
value: formatY ? formatY(set.values[i]) : set.values[i],
color: this.colors[j],
};
});
this.tip.setValues(x, y, titles[i], '', values);
this.tip.setValues(x, y, {name: titles[i], value: ''}, values, i);
this.tip.showTip();
break;
}
}
}
renderLegend() {
let s = this.data;
this.statsWrapper.textContent = '';
if(s.datasets.length > 1) {
s.datasets.map((d, i) => {
let stats = $.create('div', {
className: 'stats',
inside: this.statsWrapper
});
stats.innerHTML = `<span class="indicator">
<i style="background: ${this.colors[i]}"></i>
${d.name}
</span>`;
});
}
}
makeOverlay() {
if(this.overlayGuides) {
this.overlayGuides.forEach(g => {
@ -394,7 +414,7 @@ export default class AxisChart extends BaseChart {
type: c.unitType,
overlay: undefined,
units: c.units,
}
};
});
if(this.state.currentIndex === undefined) {
@ -406,7 +426,7 @@ export default class AxisChart extends BaseChart {
let currentUnit = d.units[this.state.currentIndex];
d.overlay = makeOverlay[d.type](currentUnit);
this.drawArea.appendChild(d.overlay);
})
});
}
@ -420,26 +440,33 @@ export default class AxisChart extends BaseChart {
}
bindOverlay() {
// on event, update overlay
this.parent.addEventListener('data-select', (e) => {
this.parent.addEventListener('data-select', () => {
this.updateOverlay();
});
}
bindUnits(units_array) {
// units_array.map(unit => {
// unit.addEventListener('click', () => {
// let index = unit.getAttribute('data-point-index');
// this.setCurrentDataPoint(index);
// });
// });
bindUnits() {
this.dataUnitComponents.map(c => {
c.units.map(unit => {
unit.addEventListener('click', () => {
let index = unit.getAttribute('data-point-index');
this.setCurrentDataPoint(index);
});
});
});
// Note: Doesn't work as tooltip is absolutely positioned
this.tip.container.addEventListener('click', () => {
let index = this.tip.container.getAttribute('data-point-index');
this.setCurrentDataPoint(index);
});
}
updateOverlay() {
this.overlayGuides.map(d => {
let currentUnit = d.units[this.state.currentIndex];
updateOverlay[d.type](currentUnit, d.overlay);
})
});
}
onLeftArrow() {
@ -451,16 +478,12 @@ export default class AxisChart extends BaseChart {
}
getDataPoint(index=this.state.currentIndex) {
// check for length
let s = this.state;
let data_point = {
index: index
index: index,
label: s.xAxis.labels[index],
values: s.datasets.map(d => d.values[index])
};
// let y = this.y[0];
// ['svg_units', 'yUnitPositions', 'values'].map(key => {
// let data_key = key.slice(0, key.length-1);
// data_point[data_key] = y[key][index];
// });
// data_point.label = this.xAxis.labels[index];
return data_point;
}
@ -501,7 +524,14 @@ export default class AxisChart extends BaseChart {
// addDataset(dataset, index) {}
// removeDataset(index = 0) {}
// updateDatasets(datasets) {}
updateDatasets(datasets) {
this.data.datasets.map((d, i) => {
if(datasets[i]) {
d.values = datasets[i];
}
});
this.update(this.data);
}
// updateDataPoint(dataPoint, index = 0) {}
// addDataPoint(dataPoint, index = 0) {}

View File

@ -143,7 +143,10 @@ export default class BaseChart {
setTimeout(() => {this.update();}, this.initTimeout);
}
this.renderLegend();
if(!onlyWidthChange) {
this.renderLegend();
}
this.setupNavigation(init);
}

View File

@ -13,15 +13,15 @@ export default class Heatmap extends BaseChart {
this.domain = options.domain || '';
this.subdomain = options.subdomain || '';
this.data = options.data || {};
this.discrete_domains = options.discrete_domains || 1;
this.count_label = options.count_label || '';
this.discreteDomains = options.discreteDomains === 0 ? 0 : 1;
this.countLabel = options.countLabel || '';
let today = new Date();
this.start = options.start || addDays(today, 365);
let legend_colors = (options.legend_colors || []).slice(0, 5);
this.legend_colors = this.validate_colors(legend_colors)
? legend_colors
let legendColors = (options.legendColors || []).slice(0, 5);
this.legendColors = this.validate_colors(legendColors)
? legendColors
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
// Fixed 5-color theme,
@ -32,6 +32,12 @@ export default class Heatmap extends BaseChart {
this.setup();
}
setMargins() {
super.setMargins();
this.leftMargin = 10;
this.translateY = 10;
}
validate_colors(colors) {
if(colors.length < 5) return 0;
@ -54,21 +60,21 @@ export default class Heatmap extends BaseChart {
this.start = new Date();
this.start.setFullYear( this.start.getFullYear() - 1 );
}
this.first_week_start = new Date(this.start.toDateString());
this.last_week_start = new Date(this.today.toDateString());
if(this.first_week_start.getDay() !== 7) {
addDays(this.first_week_start, (-1) * this.first_week_start.getDay());
this.firstWeekStart = new Date(this.start.toDateString());
this.lastWeekStart = new Date(this.today.toDateString());
if(this.firstWeekStart.getDay() !== 7) {
addDays(this.firstWeekStart, (-1) * this.firstWeekStart.getDay());
}
if(this.last_week_start.getDay() !== 7) {
addDays(this.last_week_start, (-1) * this.last_week_start.getDay());
if(this.lastWeekStart.getDay() !== 7) {
addDays(this.lastWeekStart, (-1) * this.lastWeekStart.getDay());
}
this.no_of_cols = getWeeksBetween(this.first_week_start + '', this.last_week_start + '') + 1;
this.no_of_cols = getWeeksBetween(this.firstWeekStart + '', this.lastWeekStart + '') + 1;
}
calcWidth() {
this.baseWidth = (this.no_of_cols + 3) * 12 ;
if(this.discrete_domains) {
if(this.discreteDomains) {
this.baseWidth += (12 * 12);
}
}
@ -82,21 +88,20 @@ export default class Heatmap extends BaseChart {
'data-groups',
`translate(0, 20)`
);
// Array.prototype.slice.call(
// this.container.querySelectorAll('.graph-stats-container, .sub-title, .title')
// ).map(d => {
// d.style.display = 'None';
// });
// this.chartWrapper.style.marginTop = '0px';
// this.chartWrapper.style.paddingTop = '0px';
this.container.querySelector('.title').style.display = 'None';
this.container.querySelector('.sub-title').style.display = 'None';
this.container.querySelector('.graph-stats-container').style.display = 'None';
this.chartWrapper.style.marginTop = '0px';
this.chartWrapper.style.paddingTop = '0px';
}
calc() {
let data_values = Object.keys(this.data).map(key => this.data[key]);
this.distribution = calcDistribution(data_values, this.distribution_size);
let dataValues = Object.keys(this.data).map(key => this.data[key]);
this.distribution = calcDistribution(dataValues, this.distribution_size);
this.month_names = ["January", "February", "March", "April", "May", "June",
this.monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
}
@ -110,118 +115,118 @@ export default class Heatmap extends BaseChart {
this.domainLabelGroup.textContent = '';
this.dataGroups.textContent = '';
let current_week_sunday = new Date(this.first_week_start);
this.week_col = 0;
this.current_month = current_week_sunday.getMonth();
let currentWeekSunday = new Date(this.firstWeekStart);
this.weekCol = 0;
this.currentMonth = currentWeekSunday.getMonth();
this.months = [this.current_month + ''];
this.month_weeks = {}, this.month_start_points = [];
this.month_weeks[this.current_month] = 0;
this.month_start_points.push(13);
this.months = [this.currentMonth + ''];
this.monthWeeks = {}, this.monthStartPoints = [];
this.monthWeeks[this.currentMonth] = 0;
this.monthStartPoints.push(13);
for(var i = 0; i < no_of_weeks; i++) {
let data_group, month_change = 0;
let day = new Date(current_week_sunday);
let dataGroup, monthChange = 0;
let day = new Date(currentWeekSunday);
[data_group, month_change] = this.get_week_squares_group(day, this.week_col);
this.dataGroups.appendChild(data_group);
this.week_col += 1 + parseInt(this.discrete_domains && month_change);
this.month_weeks[this.current_month]++;
if(month_change) {
this.current_month = (this.current_month + 1) % 12;
this.months.push(this.current_month + '');
this.month_weeks[this.current_month] = 1;
[dataGroup, monthChange] = this.get_week_squares_group(day, this.weekCol);
this.dataGroups.appendChild(dataGroup);
this.weekCol += 1 + parseInt(this.discreteDomains && monthChange);
this.monthWeeks[this.currentMonth]++;
if(monthChange) {
this.currentMonth = (this.currentMonth + 1) % 12;
this.months.push(this.currentMonth + '');
this.monthWeeks[this.currentMonth] = 1;
}
addDays(current_week_sunday, 7);
addDays(currentWeekSunday, 7);
}
this.render_month_labels();
}
get_week_squares_group(current_date, index) {
const no_of_weekdays = 7;
const square_side = 10;
const cell_padding = 2;
get_week_squares_group(currentDate, index) {
const noOfWeekdays = 7;
const squareSide = 10;
const cellPadding = 2;
const step = 1;
const today_time = this.today.getTime();
const todayTime = this.today.getTime();
let month_change = 0;
let week_col_change = 0;
let monthChange = 0;
let weekColChange = 0;
let data_group = makeSVGGroup(this.dataGroups, 'data-group');
let dataGroup = makeSVGGroup(this.dataGroups, 'data-group');
for(var y = 0, i = 0; i < no_of_weekdays; i += step, y += (square_side + cell_padding)) {
let data_value = 0;
for(var y = 0, i = 0; i < noOfWeekdays; i += step, y += (squareSide + cellPadding)) {
let dataValue = 0;
let colorIndex = 0;
let current_timestamp = current_date.getTime()/1000;
let timestamp = Math.floor(current_timestamp - (current_timestamp % 86400)).toFixed(1);
let currentTimestamp = currentDate.getTime()/1000;
let timestamp = Math.floor(currentTimestamp - (currentTimestamp % 86400)).toFixed(1);
if(this.data[timestamp]) {
data_value = this.data[timestamp];
dataValue = this.data[timestamp];
}
if(this.data[Math.round(timestamp)]) {
data_value = this.data[Math.round(timestamp)];
dataValue = this.data[Math.round(timestamp)];
}
if(data_value) {
colorIndex = getMaxCheckpoint(data_value, this.distribution);
if(dataValue) {
colorIndex = getMaxCheckpoint(dataValue, this.distribution);
}
let x = 13 + (index + week_col_change) * 12;
let x = 13 + (index + weekColChange) * 12;
let dataAttr = {
'data-date': getDdMmYyyy(current_date),
'data-value': data_value,
'data-day': current_date.getDay()
'data-date': getDdMmYyyy(currentDate),
'data-value': dataValue,
'data-day': currentDate.getDay()
};
let heatSquare = makeHeatSquare('day', x, y, square_side,
this.legend_colors[colorIndex], dataAttr);
let heatSquare = makeHeatSquare('day', x, y, squareSide,
this.legendColors[colorIndex], dataAttr);
data_group.appendChild(heatSquare);
dataGroup.appendChild(heatSquare);
let next_date = new Date(current_date);
addDays(next_date, 1);
if(next_date.getTime() > today_time) break;
let nextDate = new Date(currentDate);
addDays(nextDate, 1);
if(nextDate.getTime() > todayTime) break;
if(next_date.getMonth() - current_date.getMonth()) {
month_change = 1;
if(this.discrete_domains) {
week_col_change = 1;
if(nextDate.getMonth() - currentDate.getMonth()) {
monthChange = 1;
if(this.discreteDomains) {
weekColChange = 1;
}
this.month_start_points.push(13 + (index + week_col_change) * 12);
this.monthStartPoints.push(13 + (index + weekColChange) * 12);
}
current_date = next_date;
currentDate = nextDate;
}
return [data_group, month_change];
return [dataGroup, monthChange];
}
render_month_labels() {
// this.first_month_label = 1;
// if (this.first_week_start.getDate() > 8) {
// if (this.firstWeekStart.getDate() > 8) {
// this.first_month_label = 0;
// }
// this.last_month_label = 1;
// let first_month = this.months.shift();
// let first_month_start = this.month_start_points.shift();
// let first_month_start = this.monthStartPoints.shift();
// render first month if
// let last_month = this.months.pop();
// let last_month_start = this.month_start_points.pop();
// let last_month_start = this.monthStartPoints.pop();
// render last month if
this.months.shift();
this.month_start_points.shift();
this.monthStartPoints.shift();
this.months.pop();
this.month_start_points.pop();
this.monthStartPoints.pop();
this.month_start_points.map((start, i) => {
let month_name = this.month_names[this.months[i]].substring(0, 3);
this.monthStartPoints.map((start, i) => {
let month_name = this.monthNames[this.months[i]].substring(0, 3);
let text = makeText('y-value-text', start+12, 10, month_name);
this.domainLabelGroup.appendChild(text);
});
@ -233,19 +238,19 @@ export default class Heatmap extends BaseChart {
).map(el => {
el.addEventListener('mouseenter', (e) => {
let count = e.target.getAttribute('data-value');
let date_parts = e.target.getAttribute('data-date').split('-');
let dateParts = e.target.getAttribute('data-date').split('-');
let month = this.month_names[parseInt(date_parts[1])-1].substring(0, 3);
let month = this.monthNames[parseInt(dateParts[1])-1].substring(0, 3);
let g_off = this.chartWrapper.getBoundingClientRect(), p_off = e.target.getBoundingClientRect();
let gOff = this.chartWrapper.getBoundingClientRect(), pOff = e.target.getBoundingClientRect();
let width = parseInt(e.target.getAttribute('width'));
let x = p_off.left - g_off.left + (width+2)/2;
let y = p_off.top - g_off.top - (width+2)/2;
let value = count + ' ' + this.count_label;
let name = ' on ' + month + ' ' + date_parts[0] + ', ' + date_parts[2];
let x = pOff.left - gOff.left + (width+2)/2;
let y = pOff.top - gOff.top - (width+2)/2;
let value = count + ' ' + this.countLabel;
let name = ' on ' + month + ' ' + dateParts[0] + ', ' + dateParts[2];
this.tip.setValues(x, y, name, value, [], 1);
this.tip.setValues(x, y, {name: name, value: value, valueFirst: 1}, []);
this.tip.showTip();
});
});

View File

@ -67,7 +67,7 @@ export default class PercentageChart extends AggregationChart {
? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%");
this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip();
}
});

View File

@ -2,7 +2,7 @@ import AggregationChart from './AggregationChart';
import { getComponent } from '../objects/ChartComponents';
import { getOffset } from '../utils/dom';
import { getPositionByAngle } from '../utils/helpers';
import { makePath, makeArcPathStr } from '../utils/draw';
import { makeArcPathStr } from '../utils/draw';
import { lightenDarkenColor } from '../utils/colors';
import { transform } from '../utils/animation';
import { FULL_ANGLE } from '../utils/constants';
@ -39,7 +39,7 @@ export default class PieChart extends AggregationChart {
this.center = {
x: this.width / 2,
y: this.height / 2
}
};
this.radius = (this.height > this.width ? this.center.x : this.center.y);
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
@ -102,7 +102,7 @@ export default class PieChart extends AggregationChart {
return {
sliceStrings: s.sliceStrings,
colors: this.colors
}
};
}.bind(this)
]
];
@ -132,7 +132,7 @@ export default class PieChart extends AggregationChart {
let title = (this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels[i] : this.state.labels[i]) + ': ';
let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%");
this.tip.setValues(x, y, {name: title, value: percent + "%"});
this.tip.showTip();
} else {
transform(path,'translate3d(0,0,0)');

View File

@ -51,6 +51,9 @@ export default class SvgTip {
fill() {
let title;
if(this.index) {
this.container.setAttribute('data-point-index', this.index);
}
if(this.titleValueFirst) {
title = `<strong>${this.titleValue}</strong>${this.titleName}`;
} else {
@ -97,13 +100,14 @@ export default class SvgTip {
}
}
setValues(x, y, titleName = '', titleValue = '', listValues = [], titleValueFirst = 0) {
this.titleName = titleName;
this.titleValue = titleValue;
setValues(x, y, title = {}, listValues = [], index = -1) {
this.titleName = title.name;
this.titleValue = title.value;
this.listValues = listValues;
this.x = x;
this.y = y;
this.titleValueFirst = titleValueFirst;
this.titleValueFirst = title.valueFirst || 0;
this.index = index;
this.refresh();
}

View File

@ -1,4 +1,4 @@
export const VERT_SPACE_OUTSIDE_BASE_CHART = 40;
export const VERT_SPACE_OUTSIDE_BASE_CHART = 50;
export const TRANSLATE_Y_BASE_CHART = 20;
export const LEFT_MARGIN_BASE_CHART = 60;
export const RIGHT_MARGIN_BASE_CHART = 40;
@ -16,7 +16,7 @@ export const MIN_BAR_PERCENT_HEIGHT = 0.01;
export const LINE_CHART_DOT_SIZE = 4;
export const DOT_OVERLAY_SIZE_INCR = 4;
export const DEFAULT_CHAR_WIDTH = 8;
export const DEFAULT_CHAR_WIDTH = 7;
// Universal constants
export const ANGLE_RATIO = Math.PI / 180;

View File

@ -31,4 +31,9 @@ export function addDays(date, numberOfDays) {
date.setDate(date.getDate() + numberOfDays);
}
// export function getMonthName() {}
export function getMonthName(i) {
let monthNames = ["January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
];
return monthNames[i];
}

View File

@ -180,7 +180,7 @@ function makeVertLine(x, label, y1, y2, options={}) {
dy: FONT_SIZE + 'px',
'font-size': FONT_SIZE + 'px',
'text-anchor': 'middle',
innerHTML: label
innerHTML: label + ""
});
let line = createSVG('g', {
@ -337,7 +337,7 @@ export function yRegion(y1, y2, width, label) {
let labelSvg = createSVG('text', {
className: 'chart-label',
x: width - getStringWidth(label, 4.5) - LABEL_MARGIN,
x: width - getStringWidth(label+"", 4.5) - LABEL_MARGIN,
y: 0,
dy: (FONT_SIZE / -2) + 'px',
'font-size': FONT_SIZE + 'px',
@ -369,6 +369,8 @@ export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, m
height: height || meta.minHeight // TODO: correct y for positive min height
});
label += "";
if(!label && !label.length) {
return rect;
} else {
@ -385,6 +387,7 @@ export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, m
});
let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})`
});
group.appendChild(rect);
@ -403,6 +406,8 @@ export function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
r: radius
});
label += "";
if(!label && !label.length) {
return dot;
} else {
@ -420,6 +425,7 @@ export function datasetDot(x, y, radius, color, label='', index=0, meta={}) {
});
let group = createSVG('g', {
'data-point-index': index,
transform: `translate(${x}, ${y})`
});
group.appendChild(dot);
@ -481,9 +487,10 @@ export let makeOverlay = {
}
let overlay = unit.cloneNode();
let radius = unit.getAttribute('r');
overlay.setAttribute('r', radius + DOT_OVERLAY_SIZE_INCR);
overlay.style.fill = '#000000';
overlay.style.opacity = '0.4';
let fill = unit.getAttribute('fill');
overlay.setAttribute('r', parseInt(radius) + DOT_OVERLAY_SIZE_INCR);
overlay.setAttribute('fill', fill);
overlay.style.opacity = '0.6';
if(transformValue) {
overlay.setAttribute('transform', transformValue);

View File

@ -28,8 +28,13 @@
}
.graph-stats-container {
display: flex;
justify-content: space-around;
padding-top: 10px;
justify-content: space-between;
padding: 10px;
&:before,
&:after {
content: '';
display: block;
}
.stats {
padding-bottom: 15px;
}