[data] begin with zero data, bars rendered
This commit is contained in:
parent
8d2246e6c3
commit
8452e909bb
516
dist/frappe-charts.esm.js
vendored
516
dist/frappe-charts.esm.js
vendored
@ -232,6 +232,19 @@ function getStringWidth(string, charWidth) {
|
||||
return (string+"").length * charWidth;
|
||||
}
|
||||
|
||||
function getBarHeightAndYAttr(yTop, zeroLine) {
|
||||
let height, y;
|
||||
if (yTop < zeroLine) {
|
||||
height = zeroLine - yTop;
|
||||
y = yTop;
|
||||
} else {
|
||||
height = yTop - zeroLine;
|
||||
y = zeroLine;
|
||||
}
|
||||
|
||||
return [height, y];
|
||||
}
|
||||
|
||||
function equilizeNoOfElements(array1, array2,
|
||||
extra_count=array2.length - array1.length) {
|
||||
|
||||
@ -347,26 +360,6 @@ function createSVG(tag, o) {
|
||||
return element;
|
||||
}
|
||||
|
||||
function renderVerticalGradient(svgDefElem, gradientId) {
|
||||
return createSVG('linearGradient', {
|
||||
inside: svgDefElem,
|
||||
id: gradientId,
|
||||
x1: 0,
|
||||
x2: 0,
|
||||
y1: 0,
|
||||
y2: 1
|
||||
});
|
||||
}
|
||||
|
||||
function setGradientStop(gradElem, offset, color, opacity) {
|
||||
return createSVG('stop', {
|
||||
'inside': gradElem,
|
||||
'style': `stop-color: ${color}`,
|
||||
'offset': offset,
|
||||
'stop-opacity': opacity
|
||||
});
|
||||
}
|
||||
|
||||
function makeSVGContainer(parent, className, width, height) {
|
||||
return createSVG('svg', {
|
||||
className: className,
|
||||
@ -390,7 +383,13 @@ function makeSVGGroup(parent, className, transform='') {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function wrapInSVGGroup(elements, className='') {
|
||||
let g = createSVG('g', {
|
||||
className: className
|
||||
});
|
||||
elements.forEach(e => g.appendChild(e));
|
||||
return g;
|
||||
}
|
||||
|
||||
function makePath(pathStr, className='', stroke='none', fill='none') {
|
||||
return createSVG('path', {
|
||||
@ -403,20 +402,7 @@ function makePath(pathStr, className='', stroke='none', fill='none') {
|
||||
});
|
||||
}
|
||||
|
||||
function makeGradient(svgDefElem, color, lighter = false) {
|
||||
let gradientId ='path-fill-gradient' + '-' + color;
|
||||
let gradientDef = renderVerticalGradient(svgDefElem, gradientId);
|
||||
let opacities = [1, 0.6, 0.2];
|
||||
if(lighter) {
|
||||
opacities = [0.4, 0.2, 0];
|
||||
}
|
||||
|
||||
setGradientStop(gradientDef, "0%", color, opacities[0]);
|
||||
setGradientStop(gradientDef, "50%", color, opacities[1]);
|
||||
setGradientStop(gradientDef, "100%", color, opacities[2]);
|
||||
|
||||
return gradientId;
|
||||
}
|
||||
|
||||
function makeHeatSquare(className, x, y, size, fill='none', data={}) {
|
||||
let args = {
|
||||
@ -638,6 +624,37 @@ function yRegion(y1, y2, width, label) {
|
||||
return region;
|
||||
}
|
||||
|
||||
function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={}) {
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine);
|
||||
// console.log(yTop, meta.zeroLine, y, offset);
|
||||
|
||||
let rect = createSVG('rect', {
|
||||
className: `bar mini`,
|
||||
style: `fill: ${color}`,
|
||||
'data-point-index': index,
|
||||
x: x - meta.barsWidth/2,
|
||||
y: y - offset,
|
||||
width: width,
|
||||
height: height || meta.minHeight
|
||||
});
|
||||
|
||||
if(!label && !label.length) {
|
||||
return rect;
|
||||
} else {
|
||||
let text = createSVG('text', {
|
||||
className: 'data-point-value',
|
||||
x: x,
|
||||
y: y - offset,
|
||||
dy: (FONT_SIZE / 2 * -1) + 'px',
|
||||
'font-size': FONT_SIZE + 'px',
|
||||
'text-anchor': 'middle',
|
||||
innerHTML: label
|
||||
});
|
||||
|
||||
return wrapInSVGGroup([rect, text]);
|
||||
}
|
||||
}
|
||||
|
||||
const PRESET_COLOR_MAP = {
|
||||
'light-blue': '#7cd6fd',
|
||||
'blue': '#5e64ff',
|
||||
@ -872,13 +889,15 @@ class BaseChart {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.argHeight = height;
|
||||
this.type = type;
|
||||
|
||||
this.isNavigable = isNavigable;
|
||||
if(this.isNavigable) {
|
||||
this.currentIndex = 0;
|
||||
}
|
||||
|
||||
this.data = this.prepareData(data);
|
||||
this.realData = this.prepareData(data);
|
||||
this.data = this.prepareFirstData(this.realData);
|
||||
this.colors = [];
|
||||
this.config = {};
|
||||
this.state = {};
|
||||
@ -990,6 +1009,7 @@ class BaseChart {
|
||||
this.calcWidth();
|
||||
this.makeChartArea();
|
||||
|
||||
this.calc();
|
||||
this.initComponents(); // Only depend on the drawArea made in makeChartArea
|
||||
|
||||
this.setupComponents();
|
||||
@ -1002,6 +1022,7 @@ class BaseChart {
|
||||
|
||||
// TODO: remove timeout and decrease post animate time in chart component
|
||||
if(init) {
|
||||
this.data = this.realData;
|
||||
setTimeout(() => {this.update();}, 1000);
|
||||
}
|
||||
}
|
||||
@ -1029,10 +1050,10 @@ class BaseChart {
|
||||
|
||||
calc() {} // builds state
|
||||
|
||||
render(animate=true) {
|
||||
render(components=this.components, animate=true) {
|
||||
// Can decouple to this.refreshComponents() first to save animation timeout
|
||||
let elementsToAnimate = [];
|
||||
this.components.forEach(c => {
|
||||
components.forEach(c => {
|
||||
elementsToAnimate = elementsToAnimate.concat(c.update(animate));
|
||||
});
|
||||
if(elementsToAnimate.length > 0) {
|
||||
@ -1138,8 +1159,10 @@ class BaseChart {
|
||||
|
||||
const Y_AXIS_MARGIN = 60;
|
||||
|
||||
|
||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||
const DEFAULT_AXIS_CHART_TYPE = 'line';
|
||||
const AXIS_DATASET_CHART_TYPES = ['line', 'bar'];
|
||||
const BAR_CHART_SPACE_RATIO = 0.5;
|
||||
|
||||
function dataPrep(data, type) {
|
||||
data.labels = data.labels || [];
|
||||
@ -1176,23 +1199,60 @@ function dataPrep(data, type) {
|
||||
// Set labels
|
||||
//
|
||||
|
||||
// Set index
|
||||
d.index = i;
|
||||
|
||||
// Set type
|
||||
if(!d.chartType ) {
|
||||
d.chartType = type || DEFAULT_AXIS_CHART_TYPE;
|
||||
if(!AXIS_DATASET_CHART_TYPES.includes(type)) type === DEFAULT_AXIS_CHART_TYPE;
|
||||
d.chartType = type;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Markers
|
||||
|
||||
// Regions
|
||||
// Set start and end
|
||||
// data.yRegions = data.yRegions || [];
|
||||
if(data.yRegions) {
|
||||
data.yRegions.map(d => {
|
||||
if(d.end < d.start) {
|
||||
[d.start, d.end] = [d.end, start];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
function zeroDataPrep(realData) {
|
||||
let datasetLength = realData.labels.length;
|
||||
let zeroArray = new Array(datasetLength).fill(0);
|
||||
|
||||
let zeroData = {
|
||||
labels: realData.labels,
|
||||
datasets: realData.datasets.map(d => {
|
||||
return {
|
||||
name: '',
|
||||
values: zeroArray,
|
||||
chartType: d.chartType
|
||||
}
|
||||
}),
|
||||
yRegions: [
|
||||
{
|
||||
start: 0,
|
||||
end: 0,
|
||||
label: ''
|
||||
}
|
||||
],
|
||||
yMarkers: [
|
||||
{
|
||||
value: 0,
|
||||
label: ''
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return zeroData;
|
||||
}
|
||||
|
||||
class ChartComponent$1 {
|
||||
constructor({
|
||||
layerClass = '',
|
||||
@ -1215,8 +1275,9 @@ class ChartComponent$1 {
|
||||
|
||||
this.store = [];
|
||||
|
||||
this.layerClass = typeof(layerClass) === 'function'
|
||||
? layerClass() : layerClass;
|
||||
this.layerClass = layerClass;
|
||||
this.layerClass = typeof(this.layerClass) === 'function'
|
||||
? this.layerClass() : this.layerClass;
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
@ -1394,81 +1455,61 @@ let componentConfigs = {
|
||||
},
|
||||
|
||||
barGraph: {
|
||||
// opt:[
|
||||
// 'barGraph',
|
||||
// this.drawArea,
|
||||
// {
|
||||
// controller: barController,
|
||||
// index: index,
|
||||
// color: this.colors[index],
|
||||
// valuesOverPoints: this.valuesOverPoints,
|
||||
// stacked: this.barOptions && this.barOptions.stacked,
|
||||
// spaceRatio: 0.5,
|
||||
// minHeight: this.height * MIN_BAR_PERCENT_HEIGHT
|
||||
// },
|
||||
// {
|
||||
// barsWidth: this.state.unitWidth * (1 - spaceRatio),
|
||||
// barWidth: barsWidth/(stacked ? 1 : this.state.noOfDatasets),
|
||||
|
||||
// },
|
||||
// function() {
|
||||
// let s = this.state;
|
||||
// return {
|
||||
// barsWidth: this.state.unitWidth * (1 - spaceRatio),
|
||||
// barWidth: barsWidth/(stacked ? 1 : this.state.noOfDatasets),
|
||||
// positions: s.xAxisPositions,
|
||||
// labels: s.xAxisLabels,
|
||||
// }
|
||||
// }.bind(this)
|
||||
// ],
|
||||
layerClass() { return 'y-regions' + this.constants.index; },
|
||||
layerClass: function() { return 'dataset-units dataset-' + this.constants.index; },
|
||||
makeElements(data) {
|
||||
let c = this.constants;
|
||||
return data.yPositions.map((y, j) =>
|
||||
barController.draw(
|
||||
return data.yPositions.map((y, j) => {
|
||||
// console.log(data.cumulativeYPos, data.cumulativeYPos[j]);
|
||||
return datasetBar(
|
||||
data.xPositions[j],
|
||||
y,
|
||||
color,
|
||||
c.barWidth,
|
||||
c.color,
|
||||
(c.valuesOverPoints ? (c.stacked ? data.cumulativeYs[j] : data.values[j]) : ''),
|
||||
j,
|
||||
y - (data.cumulativePositions ? data.cumulativePositions[j] : y)
|
||||
y - (c.stacked ? data.cumulativeYPos[j] : y),
|
||||
{
|
||||
zeroLine: c.zeroLine,
|
||||
barsWidth: c.barsWidth,
|
||||
minHeight: c.minHeight
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
},
|
||||
postMake() {
|
||||
if((!this.constants.stacked)) {
|
||||
this.layer.setAttribute('transform',
|
||||
`translate(${unitRenderer.consts.width * index}, 0)`);
|
||||
`translate(${this.constants.width * this.constants.index}, 0)`);
|
||||
}
|
||||
},
|
||||
animateElements(newData) {
|
||||
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData);
|
||||
// [this.oldData, newData] = equilizeNoOfElements(this.oldData, newData);
|
||||
|
||||
let newPos = newData.map(d => d.end);
|
||||
let newLabels = newData.map(d => d.label);
|
||||
let newStarts = newData.map(d => d.start);
|
||||
// let newPos = newData.map(d => d.end);
|
||||
// let newLabels = newData.map(d => d.label);
|
||||
// let newStarts = newData.map(d => d.start);
|
||||
|
||||
let oldPos = this.oldData.map(d => d.end);
|
||||
let oldLabels = this.oldData.map(d => d.label);
|
||||
let oldStarts = this.oldData.map(d => d.start);
|
||||
// let oldPos = this.oldData.map(d => d.end);
|
||||
// let oldLabels = this.oldData.map(d => d.label);
|
||||
// let oldStarts = this.oldData.map(d => d.start);
|
||||
|
||||
this.render(oldPos.map((pos, i) => {
|
||||
return {
|
||||
start: oldStarts[i],
|
||||
end: oldPos[i],
|
||||
label: newLabels[i]
|
||||
}
|
||||
}));
|
||||
// this.render(oldPos.map((pos, i) => {
|
||||
// return {
|
||||
// start: oldStarts[i],
|
||||
// end: oldPos[i],
|
||||
// label: newLabels[i]
|
||||
// }
|
||||
// }));
|
||||
|
||||
let animateElements = [];
|
||||
// let animateElements = [];
|
||||
|
||||
this.store.map((rectGroup, i) => {
|
||||
animateElements = animateElements.concat(animateRegion(
|
||||
rectGroup, newStarts[i], newPos[i], oldPos[i]
|
||||
));
|
||||
});
|
||||
// this.store.map((rectGroup, i) => {
|
||||
// animateElements = animateElements.concat(animateRegion(
|
||||
// rectGroup, newStarts[i], newPos[i], oldPos[i]
|
||||
// ));
|
||||
// });
|
||||
|
||||
return animateElements;
|
||||
// return animateElements;
|
||||
}
|
||||
},
|
||||
|
||||
@ -1486,101 +1527,6 @@ function getComponent(name, constants, getData) {
|
||||
return new ChartComponent$1(config);
|
||||
}
|
||||
|
||||
function getPaths(yList, xList, color, heatline=false, regionFill=false) {
|
||||
let pointsList = yList.map((y, i) => (xList[i] + ',' + y));
|
||||
let pointsStr = pointsList.join("L");
|
||||
let path = makePath("M"+pointsStr, 'line-graph-path', color);
|
||||
|
||||
// HeatLine
|
||||
if(heatline) {
|
||||
let gradient_id = makeGradient(this.svgDefs, color);
|
||||
path.style.stroke = `url(#${gradient_id})`;
|
||||
}
|
||||
|
||||
let components = [path];
|
||||
|
||||
// Region
|
||||
if(regionFill) {
|
||||
let gradient_id_region = makeGradient(this.svgDefs, color, true);
|
||||
|
||||
let zeroLine = this.state.yAxis.zeroLine;
|
||||
// TODO: use zeroLine OR minimum
|
||||
let pathStr = "M" + `0,${zeroLine}L` + pointsStr + `L${this.width},${zeroLine}`;
|
||||
components.push(makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id_region})`));
|
||||
}
|
||||
|
||||
return components;
|
||||
}
|
||||
|
||||
// class BarChart extends AxisChart {
|
||||
// constructor(args) {
|
||||
// super(args);
|
||||
// this.type = 'bar';
|
||||
// this.setup();
|
||||
// }
|
||||
|
||||
// configure(args) {
|
||||
// super.configure(args);
|
||||
// this.config.xAxisMode = args.xAxisMode || 'tick';
|
||||
// this.config.yAxisMode = args.yAxisMode || 'span';
|
||||
// }
|
||||
|
||||
// // =================================
|
||||
|
||||
// makeOverlay() {
|
||||
// // Just make one out of the first element
|
||||
// let index = this.xAxisLabels.length - 1;
|
||||
// let unit = this.y[0].svg_units[index];
|
||||
// this.setCurrentDataPoint(index);
|
||||
|
||||
// if(this.overlay) {
|
||||
// this.overlay.parentNode.removeChild(this.overlay);
|
||||
// }
|
||||
// this.overlay = unit.cloneNode();
|
||||
// this.overlay.style.fill = '#000000';
|
||||
// this.overlay.style.opacity = '0.4';
|
||||
// this.drawArea.appendChild(this.overlay);
|
||||
// }
|
||||
|
||||
// bindOverlay() {
|
||||
// // on event, update overlay
|
||||
// this.parent.addEventListener('data-select', (e) => {
|
||||
// this.update_overlay(e.svg_unit);
|
||||
// });
|
||||
// }
|
||||
|
||||
// bind_units(units_array) {
|
||||
// units_array.map(unit => {
|
||||
// unit.addEventListener('click', () => {
|
||||
// let index = unit.getAttribute('data-point-index');
|
||||
// this.setCurrentDataPoint(index);
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
||||
// update_overlay(unit) {
|
||||
// let attributes = [];
|
||||
// Object.keys(unit.attributes).map(index => {
|
||||
// attributes.push(unit.attributes[index]);
|
||||
// });
|
||||
|
||||
// attributes.filter(attr => attr.specified).map(attr => {
|
||||
// this.overlay.setAttribute(attr.name, attr.nodeValue);
|
||||
// });
|
||||
|
||||
// this.overlay.style.fill = '#000000';
|
||||
// this.overlay.style.opacity = '0.4';
|
||||
// }
|
||||
|
||||
// onLeftArrow() {
|
||||
// this.setCurrentDataPoint(this.currentIndex - 1);
|
||||
// }
|
||||
|
||||
// onRightArrow() {
|
||||
// this.setCurrentDataPoint(this.currentIndex + 1);
|
||||
// }
|
||||
// }
|
||||
|
||||
function normalize(x) {
|
||||
// Calculates mantissa and exponent of a number
|
||||
// Returns normalized number and exponent
|
||||
@ -1757,17 +1703,7 @@ function getZeroIndex(yPts) {
|
||||
return zeroIndex;
|
||||
}
|
||||
|
||||
function getRealIntervals(max, noOfIntervals, min = 0, asc = 1) {
|
||||
let range = max - min;
|
||||
let part = range * 1.0 / noOfIntervals;
|
||||
let intervals = [];
|
||||
|
||||
for(var i = 0; i <= noOfIntervals; i++) {
|
||||
intervals.push(min + part * i);
|
||||
}
|
||||
|
||||
return asc ? intervals : intervals.reverse();
|
||||
}
|
||||
|
||||
function getIntervalSize(orderedArray) {
|
||||
return orderedArray[1] - orderedArray[0];
|
||||
@ -1777,6 +1713,10 @@ function getValueRange(orderedArray) {
|
||||
return orderedArray[orderedArray.length-1] - orderedArray[0];
|
||||
}
|
||||
|
||||
function scale(val, yAxis) {
|
||||
return floatTwo(yAxis.zeroLine - val * yAxis.scaleMultiplier)
|
||||
}
|
||||
|
||||
function calcDistribution(values, distributionSize) {
|
||||
// Assume non-negative values,
|
||||
// implying distribution minimum at zero
|
||||
@ -1805,19 +1745,19 @@ class AxisChart extends BaseChart {
|
||||
this.valuesOverPoints = args.valuesOverPoints;
|
||||
this.formatTooltipY = args.formatTooltipY;
|
||||
this.formatTooltipX = args.formatTooltipX;
|
||||
this.barOptions = args.barOptions;
|
||||
this.lineOptions = args.lineOptions;
|
||||
this.barOptions = args.barOptions || {};
|
||||
this.lineOptions = args.lineOptions || {};
|
||||
this.type = args.type || 'line';
|
||||
|
||||
this.xAxisMode = args.xAxisMode || 'span';
|
||||
this.yAxisMode = args.yAxisMode || 'span';
|
||||
|
||||
this.zeroLine = this.height;
|
||||
this.setTrivialState();
|
||||
// this.setTrivialState();
|
||||
this.setup();
|
||||
}
|
||||
|
||||
configure(args) {
|
||||
configure(args) {3;
|
||||
super.configure();
|
||||
|
||||
// TODO: set in options and use
|
||||
@ -1826,38 +1766,6 @@ class AxisChart extends BaseChart {
|
||||
this.config.yAxisMode = args.yAxisMode;
|
||||
}
|
||||
|
||||
setTrivialState() {
|
||||
// Define data and stuff
|
||||
let yTempPos = getRealIntervals(this.height, 4, 0, 0);
|
||||
|
||||
this.state = {
|
||||
xAxis: {
|
||||
positions: [],
|
||||
labels: [],
|
||||
},
|
||||
yAxis: {
|
||||
positions: yTempPos,
|
||||
labels: yTempPos.map(d => ""),
|
||||
},
|
||||
yRegions: [
|
||||
{
|
||||
start: this.height,
|
||||
end: this.height,
|
||||
label: ''
|
||||
}
|
||||
],
|
||||
yMarkers: [
|
||||
{
|
||||
position: this.height,
|
||||
label: ''
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
this.calcWidth();
|
||||
this.calcXPositions(this.state);
|
||||
}
|
||||
|
||||
setMargins() {
|
||||
super.setMargins();
|
||||
this.translateXLeft = Y_AXIS_MARGIN;
|
||||
@ -1868,10 +1776,12 @@ class AxisChart extends BaseChart {
|
||||
return dataPrep(data, this.type);
|
||||
}
|
||||
|
||||
prepareFirstData(data=this.data) {
|
||||
return zeroDataPrep(data);
|
||||
}
|
||||
|
||||
calc() {
|
||||
|
||||
this.calcXPositions();
|
||||
|
||||
this.calcYAxisParameters(this.getAllYValues(), this.type === 'line');
|
||||
}
|
||||
|
||||
@ -1905,61 +1815,60 @@ class AxisChart extends BaseChart {
|
||||
};
|
||||
|
||||
this.calcYUnits();
|
||||
this.calcYMaximums();
|
||||
this.calcYExtremes();
|
||||
this.calcYRegions();
|
||||
}
|
||||
|
||||
calcYUnits() {
|
||||
let s = this.state;
|
||||
this.data.datasets.map(d => {
|
||||
d.positions = d.values.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
let scaleAll = values => values.map(val => scale(val, s.yAxis));
|
||||
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
this.data.datasets.map((d, i) => {
|
||||
d.cumulativePositions = d.cumulativeYs.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
}
|
||||
s.datasets = this.data.datasets.map((d, i) => {
|
||||
let values = d.values;
|
||||
let cumulativeYs = d.cumulativeYs || [];
|
||||
return {
|
||||
name: d.name,
|
||||
index: i,
|
||||
chartType: d.chartType,
|
||||
|
||||
values: values,
|
||||
yPositions: scaleAll(values),
|
||||
|
||||
cumulativeYs: cumulativeYs,
|
||||
cumulativeYPos: scaleAll(cumulativeYs),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
calcYMaximums() {
|
||||
calcYExtremes() {
|
||||
let s = this.state;
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
s.yExtremes = this.data.datasets[this.data.datasets.length - 1].cumulativePositions;
|
||||
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativeYPos;
|
||||
return;
|
||||
}
|
||||
s.yExtremes = new Array(s.datasetLength).fill(9999);
|
||||
this.data.datasets.map((d, i) => {
|
||||
d.positions.map((pos, j) => {
|
||||
s.datasets.map((d, i) => {
|
||||
d.yPositions.map((pos, j) => {
|
||||
if(pos < s.yExtremes[j]) {
|
||||
s.yExtremes[j] = pos;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Tooltip refresh should not be needed?
|
||||
// this.chartWrapper.removeChild(this.tip.container);
|
||||
// this.make_tooltip();
|
||||
}
|
||||
|
||||
calcYRegions() {
|
||||
let s = this.state;
|
||||
if(this.data.yMarkers) {
|
||||
this.state.yMarkers = this.data.yMarkers.map(d => {
|
||||
d.position = floatTwo(s.yAxis.zeroLine - d.value * s.yAxis.scaleMultiplier);
|
||||
d.position = scale(d.value, s.yAxis);
|
||||
d.label += ': ' + d.value;
|
||||
return d;
|
||||
});
|
||||
}
|
||||
if(this.data.yRegions) {
|
||||
this.state.yRegions = this.data.yRegions.map(d => {
|
||||
if(d.end < d.start) {
|
||||
[d.start, d.end] = [d.end, start];
|
||||
}
|
||||
d.start = floatTwo(s.yAxis.zeroLine - d.start * s.yAxis.scaleMultiplier);
|
||||
d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier);
|
||||
d.start = scale(d.start, s.yAxis);
|
||||
d.end = scale(d.end, s.yAxis);
|
||||
return d;
|
||||
});
|
||||
}
|
||||
@ -1982,6 +1891,9 @@ class AxisChart extends BaseChart {
|
||||
}
|
||||
|
||||
initComponents() {
|
||||
let s = this.state;
|
||||
// console.log('this.state', Object.assign({}, this.state));
|
||||
// console.log('this.state', this.state);
|
||||
this.componentConfigs = [
|
||||
[
|
||||
'yAxis',
|
||||
@ -2008,7 +1920,57 @@ class AxisChart extends BaseChart {
|
||||
pos: 'right'
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
this.componentConfigs.map(args => {
|
||||
args.push(
|
||||
function() {
|
||||
return this.state[args[0]];
|
||||
}.bind(this)
|
||||
);
|
||||
});
|
||||
|
||||
let barDatasets = this.state.datasets.filter(d => d.chartType === 'bar');
|
||||
let lineDatasets = this.state.datasets.filter(d => d.chartType === 'line');
|
||||
|
||||
// console.log('barDatasets', barDatasets, this.state.datasets);
|
||||
|
||||
// Bars
|
||||
let spaceRatio = this.barOptions.spaceRatio || BAR_CHART_SPACE_RATIO;
|
||||
let barsWidth = s.unitWidth * (1 - spaceRatio);
|
||||
let barWidth = barsWidth/(this.barOptions.stacked ? 1 : barDatasets.length);
|
||||
|
||||
let barsConfigs = barDatasets.map(d => {
|
||||
let index = d.index;
|
||||
return [
|
||||
'barGraph',
|
||||
{
|
||||
index: index,
|
||||
color: this.colors[index],
|
||||
|
||||
// same for all datasets
|
||||
valuesOverPoints: this.valuesOverPoints,
|
||||
minHeight: this.height * MIN_BAR_PERCENT_HEIGHT,
|
||||
barsWidth: barsWidth,
|
||||
barWidth: barWidth,
|
||||
zeroLine: s.yAxis.zeroLine
|
||||
},
|
||||
function() {
|
||||
let s = this.state;
|
||||
let d = s.datasets[index];
|
||||
return {
|
||||
xPositions: s.xAxis.positions,
|
||||
yPositions: d.yPositions,
|
||||
cumulativeYPos: d.cumulativeYPos,
|
||||
|
||||
values: d.values,
|
||||
cumulativeYs: d.cumulativeYs
|
||||
};
|
||||
}.bind(this)
|
||||
];
|
||||
});
|
||||
|
||||
let markerConfigs = [
|
||||
[
|
||||
'yMarkers',
|
||||
{
|
||||
@ -2017,17 +1979,23 @@ class AxisChart extends BaseChart {
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
markerConfigs.map(args => {
|
||||
args.push(
|
||||
function() {
|
||||
return this.state[args[0]];
|
||||
}.bind(this)
|
||||
);
|
||||
});
|
||||
|
||||
this.componentConfigs = this.componentConfigs.concat(barsConfigs, markerConfigs);
|
||||
}
|
||||
|
||||
setupComponents() {
|
||||
let optionals = ['yMarkers', 'yRegions'];
|
||||
this.components = new Map(this.componentConfigs
|
||||
.filter(args => !optionals.includes(args[0]) || this.data[args[0]])
|
||||
.filter(args => !optionals.includes(args[0]) || this.state[args[0]] || args[0] === 'barGraph')
|
||||
.map(args => {
|
||||
args.push(
|
||||
function() {
|
||||
return this.state[args[0]];
|
||||
}.bind(this)
|
||||
);
|
||||
return [args[0], getComponent(...args)];
|
||||
}));
|
||||
}
|
||||
|
||||
2
dist/frappe-charts.min.cjs.js
vendored
2
dist/frappe-charts.min.cjs.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.esm.js
vendored
2
dist/frappe-charts.min.esm.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.iife.js
vendored
2
dist/frappe-charts.min.iife.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.iife.js.map
vendored
2
dist/frappe-charts.min.iife.js.map
vendored
File diff suppressed because one or more lines are too long
2
docs/assets/js/frappe-charts.min.js
vendored
2
docs/assets/js/frappe-charts.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -177,7 +177,7 @@ let type_data = {
|
||||
{
|
||||
name: "Yet Another",
|
||||
values: [15, 20, -3, -15, 58, 12, -17, 37],
|
||||
chartType: 'line'
|
||||
chartType: 'bar'
|
||||
}
|
||||
|
||||
// temp : Stacked
|
||||
|
||||
@ -1,16 +1,15 @@
|
||||
import BaseChart from './BaseChart';
|
||||
import { dataPrep } from './axis-chart-utils';
|
||||
import { dataPrep, zeroDataPrep } from './axis-chart-utils';
|
||||
import { Y_AXIS_MARGIN } from '../utils/constants';
|
||||
import { getComponent } from '../objects/ChartComponents';
|
||||
import { BarChartController, LineChartController, getPaths } from '../objects/AxisChartControllers';
|
||||
import { AxisChartRenderer } from '../utils/draw';
|
||||
import { getOffset, fire } from '../utils/dom';
|
||||
import { equilizeNoOfElements } from '../utils/draw-utils';
|
||||
import { Animator, translateHoriLine } from '../utils/animate';
|
||||
import { runSMILAnimation } from '../utils/animation';
|
||||
import { getRealIntervals, calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex } from '../utils/intervals';
|
||||
import { getRealIntervals, calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex, scale } from '../utils/intervals';
|
||||
import { floatTwo, fillArray, bindChange } from '../utils/helpers';
|
||||
import { MIN_BAR_PERCENT_HEIGHT, DEFAULT_AXIS_CHART_TYPE } from '../utils/constants';
|
||||
import { MIN_BAR_PERCENT_HEIGHT, DEFAULT_AXIS_CHART_TYPE, BAR_CHART_SPACE_RATIO } from '../utils/constants';
|
||||
|
||||
export default class AxisChart extends BaseChart {
|
||||
constructor(args) {
|
||||
@ -19,19 +18,19 @@ export default class AxisChart extends BaseChart {
|
||||
this.valuesOverPoints = args.valuesOverPoints;
|
||||
this.formatTooltipY = args.formatTooltipY;
|
||||
this.formatTooltipX = args.formatTooltipX;
|
||||
this.barOptions = args.barOptions;
|
||||
this.lineOptions = args.lineOptions;
|
||||
this.barOptions = args.barOptions || {};
|
||||
this.lineOptions = args.lineOptions || {};
|
||||
this.type = args.type || 'line';
|
||||
|
||||
this.xAxisMode = args.xAxisMode || 'span';
|
||||
this.yAxisMode = args.yAxisMode || 'span';
|
||||
|
||||
this.zeroLine = this.height;
|
||||
this.setTrivialState();
|
||||
// this.setTrivialState();
|
||||
this.setup();
|
||||
}
|
||||
|
||||
configure(args) {
|
||||
configure(args) {3
|
||||
super.configure();
|
||||
|
||||
// TODO: set in options and use
|
||||
@ -40,38 +39,6 @@ export default class AxisChart extends BaseChart {
|
||||
this.config.yAxisMode = args.yAxisMode;
|
||||
}
|
||||
|
||||
setTrivialState() {
|
||||
// Define data and stuff
|
||||
let yTempPos = getRealIntervals(this.height, 4, 0, 0);
|
||||
|
||||
this.state = {
|
||||
xAxis: {
|
||||
positions: [],
|
||||
labels: [],
|
||||
},
|
||||
yAxis: {
|
||||
positions: yTempPos,
|
||||
labels: yTempPos.map(d => ""),
|
||||
},
|
||||
yRegions: [
|
||||
{
|
||||
start: this.height,
|
||||
end: this.height,
|
||||
label: ''
|
||||
}
|
||||
],
|
||||
yMarkers: [
|
||||
{
|
||||
position: this.height,
|
||||
label: ''
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
this.calcWidth();
|
||||
this.calcXPositions(this.state);
|
||||
}
|
||||
|
||||
setMargins() {
|
||||
super.setMargins();
|
||||
this.translateXLeft = Y_AXIS_MARGIN;
|
||||
@ -82,10 +49,12 @@ export default class AxisChart extends BaseChart {
|
||||
return dataPrep(data, this.type);
|
||||
}
|
||||
|
||||
prepareFirstData(data=this.data) {
|
||||
return zeroDataPrep(data);
|
||||
}
|
||||
|
||||
calc() {
|
||||
|
||||
this.calcXPositions();
|
||||
|
||||
this.calcYAxisParameters(this.getAllYValues(), this.type === 'line');
|
||||
}
|
||||
|
||||
@ -119,61 +88,60 @@ export default class AxisChart extends BaseChart {
|
||||
}
|
||||
|
||||
this.calcYUnits();
|
||||
this.calcYMaximums();
|
||||
this.calcYExtremes();
|
||||
this.calcYRegions();
|
||||
}
|
||||
|
||||
calcYUnits() {
|
||||
let s = this.state;
|
||||
this.data.datasets.map(d => {
|
||||
d.positions = d.values.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
let scaleAll = values => values.map(val => scale(val, s.yAxis));
|
||||
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
this.data.datasets.map((d, i) => {
|
||||
d.cumulativePositions = d.cumulativeYs.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
}
|
||||
s.datasets = this.data.datasets.map((d, i) => {
|
||||
let values = d.values;
|
||||
let cumulativeYs = d.cumulativeYs || [];
|
||||
return {
|
||||
name: d.name,
|
||||
index: i,
|
||||
chartType: d.chartType,
|
||||
|
||||
values: values,
|
||||
yPositions: scaleAll(values),
|
||||
|
||||
cumulativeYs: cumulativeYs,
|
||||
cumulativeYPos: scaleAll(cumulativeYs),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
calcYMaximums() {
|
||||
calcYExtremes() {
|
||||
let s = this.state;
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
s.yExtremes = this.data.datasets[this.data.datasets.length - 1].cumulativePositions;
|
||||
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativeYPos;
|
||||
return;
|
||||
}
|
||||
s.yExtremes = new Array(s.datasetLength).fill(9999);
|
||||
this.data.datasets.map((d, i) => {
|
||||
d.positions.map((pos, j) => {
|
||||
s.datasets.map((d, i) => {
|
||||
d.yPositions.map((pos, j) => {
|
||||
if(pos < s.yExtremes[j]) {
|
||||
s.yExtremes[j] = pos;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Tooltip refresh should not be needed?
|
||||
// this.chartWrapper.removeChild(this.tip.container);
|
||||
// this.make_tooltip();
|
||||
}
|
||||
|
||||
calcYRegions() {
|
||||
let s = this.state;
|
||||
if(this.data.yMarkers) {
|
||||
this.state.yMarkers = this.data.yMarkers.map(d => {
|
||||
d.position = floatTwo(s.yAxis.zeroLine - d.value * s.yAxis.scaleMultiplier);
|
||||
d.position = scale(d.value, s.yAxis);
|
||||
d.label += ': ' + d.value;
|
||||
return d;
|
||||
});
|
||||
}
|
||||
if(this.data.yRegions) {
|
||||
this.state.yRegions = this.data.yRegions.map(d => {
|
||||
if(d.end < d.start) {
|
||||
[d.start, d.end] = [d.end, start];
|
||||
}
|
||||
d.start = floatTwo(s.yAxis.zeroLine - d.start * s.yAxis.scaleMultiplier);
|
||||
d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier);
|
||||
d.start = scale(d.start, s.yAxis);
|
||||
d.end = scale(d.end, s.yAxis);
|
||||
return d;
|
||||
});
|
||||
}
|
||||
@ -196,6 +164,9 @@ export default class AxisChart extends BaseChart {
|
||||
}
|
||||
|
||||
initComponents() {
|
||||
let s = this.state;
|
||||
// console.log('this.state', Object.assign({}, this.state));
|
||||
// console.log('this.state', this.state);
|
||||
this.componentConfigs = [
|
||||
[
|
||||
'yAxis',
|
||||
@ -222,7 +193,57 @@ export default class AxisChart extends BaseChart {
|
||||
pos: 'right'
|
||||
}
|
||||
],
|
||||
];
|
||||
|
||||
this.componentConfigs.map(args => {
|
||||
args.push(
|
||||
function() {
|
||||
return this.state[args[0]];
|
||||
}.bind(this)
|
||||
);
|
||||
});
|
||||
|
||||
let barDatasets = this.state.datasets.filter(d => d.chartType === 'bar');
|
||||
let lineDatasets = this.state.datasets.filter(d => d.chartType === 'line');
|
||||
|
||||
// console.log('barDatasets', barDatasets, this.state.datasets);
|
||||
|
||||
// Bars
|
||||
let spaceRatio = this.barOptions.spaceRatio || BAR_CHART_SPACE_RATIO;
|
||||
let barsWidth = s.unitWidth * (1 - spaceRatio);
|
||||
let barWidth = barsWidth/(this.barOptions.stacked ? 1 : barDatasets.length);
|
||||
|
||||
let barsConfigs = barDatasets.map(d => {
|
||||
let index = d.index;
|
||||
return [
|
||||
'barGraph',
|
||||
{
|
||||
index: index,
|
||||
color: this.colors[index],
|
||||
|
||||
// same for all datasets
|
||||
valuesOverPoints: this.valuesOverPoints,
|
||||
minHeight: this.height * MIN_BAR_PERCENT_HEIGHT,
|
||||
barsWidth: barsWidth,
|
||||
barWidth: barWidth,
|
||||
zeroLine: s.yAxis.zeroLine
|
||||
},
|
||||
function() {
|
||||
let s = this.state;
|
||||
let d = s.datasets[index];
|
||||
return {
|
||||
xPositions: s.xAxis.positions,
|
||||
yPositions: d.yPositions,
|
||||
cumulativeYPos: d.cumulativeYPos,
|
||||
|
||||
values: d.values,
|
||||
cumulativeYs: d.cumulativeYs
|
||||
};
|
||||
}.bind(this)
|
||||
];
|
||||
});
|
||||
|
||||
let markerConfigs = [
|
||||
[
|
||||
'yMarkers',
|
||||
{
|
||||
@ -231,17 +252,23 @@ export default class AxisChart extends BaseChart {
|
||||
}
|
||||
]
|
||||
];
|
||||
|
||||
markerConfigs.map(args => {
|
||||
args.push(
|
||||
function() {
|
||||
return this.state[args[0]];
|
||||
}.bind(this)
|
||||
);
|
||||
});
|
||||
|
||||
this.componentConfigs = this.componentConfigs.concat(barsConfigs, markerConfigs);
|
||||
}
|
||||
|
||||
setupComponents() {
|
||||
let optionals = ['yMarkers', 'yRegions'];
|
||||
this.components = new Map(this.componentConfigs
|
||||
.filter(args => !optionals.includes(args[0]) || this.data[args[0]])
|
||||
.filter(args => !optionals.includes(args[0]) || this.state[args[0]] || args[0] === 'barGraph')
|
||||
.map(args => {
|
||||
args.push(
|
||||
function() {
|
||||
return this.state[args[0]];
|
||||
}.bind(this)
|
||||
);
|
||||
return [args[0], getComponent(...args)];
|
||||
}));
|
||||
}
|
||||
|
||||
@ -28,13 +28,15 @@ export default class BaseChart {
|
||||
this.title = title;
|
||||
this.subtitle = subtitle;
|
||||
this.argHeight = height;
|
||||
this.type = type;
|
||||
|
||||
this.isNavigable = isNavigable;
|
||||
if(this.isNavigable) {
|
||||
this.currentIndex = 0;
|
||||
}
|
||||
|
||||
this.data = this.prepareData(data);;
|
||||
this.realData = this.prepareData(data);
|
||||
this.data = this.prepareFirstData(this.realData);
|
||||
this.colors = [];
|
||||
this.config = {};
|
||||
this.state = {};
|
||||
@ -148,6 +150,7 @@ export default class BaseChart {
|
||||
this.calcWidth();
|
||||
this.makeChartArea();
|
||||
|
||||
this.calc();
|
||||
this.initComponents(); // Only depend on the drawArea made in makeChartArea
|
||||
|
||||
this.setupComponents();
|
||||
@ -160,6 +163,7 @@ export default class BaseChart {
|
||||
|
||||
// TODO: remove timeout and decrease post animate time in chart component
|
||||
if(init) {
|
||||
this.data = this.realData;
|
||||
setTimeout(() => {this.update();}, 1000);
|
||||
}
|
||||
}
|
||||
@ -187,10 +191,10 @@ export default class BaseChart {
|
||||
|
||||
calc() {} // builds state
|
||||
|
||||
render(animate=true) {
|
||||
render(components=this.components, animate=true) {
|
||||
// Can decouple to this.refreshComponents() first to save animation timeout
|
||||
let elementsToAnimate = [];
|
||||
this.components.forEach(c => {
|
||||
components.forEach(c => {
|
||||
elementsToAnimate = elementsToAnimate.concat(c.update(animate));
|
||||
});
|
||||
if(elementsToAnimate.length > 0) {
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { floatTwo, fillArray } from '../utils/helpers';
|
||||
import { DEFAULT_AXIS_CHART_TYPE } from '../utils/constants';
|
||||
import { DEFAULT_AXIS_CHART_TYPE, AXIS_DATASET_CHART_TYPES } from '../utils/constants';
|
||||
|
||||
export function dataPrep(data, type) {
|
||||
data.labels = data.labels || [];
|
||||
@ -36,19 +36,56 @@ export function dataPrep(data, type) {
|
||||
// Set labels
|
||||
//
|
||||
|
||||
// Set index
|
||||
d.index = i;
|
||||
|
||||
// Set type
|
||||
if(!d.chartType ) {
|
||||
d.chartType = type || DEFAULT_AXIS_CHART_TYPE;
|
||||
if(!AXIS_DATASET_CHART_TYPES.includes(type)) type === DEFAULT_AXIS_CHART_TYPE;
|
||||
d.chartType = type;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
// Markers
|
||||
|
||||
// Regions
|
||||
// Set start and end
|
||||
// data.yRegions = data.yRegions || [];
|
||||
if(data.yRegions) {
|
||||
data.yRegions.map(d => {
|
||||
if(d.end < d.start) {
|
||||
[d.start, d.end] = [d.end, start];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
export function zeroDataPrep(realData) {
|
||||
let datasetLength = realData.labels.length;
|
||||
let zeroArray = new Array(datasetLength).fill(0);
|
||||
|
||||
let zeroData = {
|
||||
labels: realData.labels,
|
||||
datasets: realData.datasets.map(d => {
|
||||
return {
|
||||
name: '',
|
||||
values: zeroArray,
|
||||
chartType: d.chartType
|
||||
}
|
||||
}),
|
||||
yRegions: [
|
||||
{
|
||||
start: 0,
|
||||
end: 0,
|
||||
label: ''
|
||||
}
|
||||
],
|
||||
yMarkers: [
|
||||
{
|
||||
value: 0,
|
||||
label: ''
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
return zeroData;
|
||||
}
|
||||
@ -67,36 +67,6 @@ export class BarChartController extends AxisChartController {
|
||||
? m.options.stacked : m.noOfDatasets);
|
||||
}
|
||||
|
||||
draw(x, yTop, color, label='', index=0, offset=0) {
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine);
|
||||
|
||||
let rect = createSVG('rect', {
|
||||
className: `bar mini`,
|
||||
style: `fill: ${color}`,
|
||||
'data-point-index': index,
|
||||
x: x - this.consts.barsWidth/2,
|
||||
y: y - offset,
|
||||
width: this.consts.width,
|
||||
height: height || this.consts.minHeight
|
||||
});
|
||||
|
||||
if(!label && !label.length) {
|
||||
return rect;
|
||||
} else {
|
||||
let text = createSVG('text', {
|
||||
className: 'data-point-value',
|
||||
x: x,
|
||||
y: y - offset,
|
||||
dy: (FONT_SIZE / 2 * -1) + 'px',
|
||||
'font-size': FONT_SIZE + 'px',
|
||||
'text-anchor': 'middle',
|
||||
innerHTML: label
|
||||
});
|
||||
|
||||
return wrapInSVGGroup([rect, text]);
|
||||
}
|
||||
}
|
||||
|
||||
animate(bar, x, yTop, index, noOfDatasets) {
|
||||
let start = x - this.meta.unitWidth/4;
|
||||
let width = (this.meta.unitWidth/2)/noOfDatasets;
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { makeSVGGroup } from '../utils/draw';
|
||||
import { xLine, yLine, yMarker, yRegion } from '../utils/draw';
|
||||
import { xLine, yLine, yMarker, yRegion, datasetBar } from '../utils/draw';
|
||||
import { equilizeNoOfElements } from '../utils/draw-utils';
|
||||
import { Animator, translateHoriLine, translateVertLine, animateRegion } from '../utils/animate';
|
||||
|
||||
@ -25,8 +25,9 @@ class ChartComponent {
|
||||
|
||||
this.store = [];
|
||||
|
||||
this.layerClass = typeof(layerClass) === 'function'
|
||||
? layerClass() : layerClass;
|
||||
this.layerClass = layerClass;
|
||||
this.layerClass = typeof(this.layerClass) === 'function'
|
||||
? this.layerClass() : this.layerClass;
|
||||
|
||||
this.refresh();
|
||||
}
|
||||
@ -204,81 +205,61 @@ let componentConfigs = {
|
||||
},
|
||||
|
||||
barGraph: {
|
||||
// opt:[
|
||||
// 'barGraph',
|
||||
// this.drawArea,
|
||||
// {
|
||||
// controller: barController,
|
||||
// index: index,
|
||||
// color: this.colors[index],
|
||||
// valuesOverPoints: this.valuesOverPoints,
|
||||
// stacked: this.barOptions && this.barOptions.stacked,
|
||||
// spaceRatio: 0.5,
|
||||
// minHeight: this.height * MIN_BAR_PERCENT_HEIGHT
|
||||
// },
|
||||
// {
|
||||
// barsWidth: this.state.unitWidth * (1 - spaceRatio),
|
||||
// barWidth: barsWidth/(stacked ? 1 : this.state.noOfDatasets),
|
||||
|
||||
// },
|
||||
// function() {
|
||||
// let s = this.state;
|
||||
// return {
|
||||
// barsWidth: this.state.unitWidth * (1 - spaceRatio),
|
||||
// barWidth: barsWidth/(stacked ? 1 : this.state.noOfDatasets),
|
||||
// positions: s.xAxisPositions,
|
||||
// labels: s.xAxisLabels,
|
||||
// }
|
||||
// }.bind(this)
|
||||
// ],
|
||||
layerClass() { return 'y-regions' + this.constants.index; },
|
||||
layerClass: function() { return 'dataset-units dataset-' + this.constants.index; },
|
||||
makeElements(data) {
|
||||
let c = this.constants;
|
||||
return data.yPositions.map((y, j) =>
|
||||
barController.draw(
|
||||
return data.yPositions.map((y, j) => {
|
||||
// console.log(data.cumulativeYPos, data.cumulativeYPos[j]);
|
||||
return datasetBar(
|
||||
data.xPositions[j],
|
||||
y,
|
||||
color,
|
||||
c.barWidth,
|
||||
c.color,
|
||||
(c.valuesOverPoints ? (c.stacked ? data.cumulativeYs[j] : data.values[j]) : ''),
|
||||
j,
|
||||
y - (data.cumulativePositions ? data.cumulativePositions[j] : y)
|
||||
y - (c.stacked ? data.cumulativeYPos[j] : y),
|
||||
{
|
||||
zeroLine: c.zeroLine,
|
||||
barsWidth: c.barsWidth,
|
||||
minHeight: c.minHeight
|
||||
}
|
||||
)
|
||||
);
|
||||
});
|
||||
},
|
||||
postMake() {
|
||||
if((!this.constants.stacked)) {
|
||||
this.layer.setAttribute('transform',
|
||||
`translate(${unitRenderer.consts.width * index}, 0)`);
|
||||
`translate(${this.constants.width * this.constants.index}, 0)`);
|
||||
}
|
||||
},
|
||||
animateElements(newData) {
|
||||
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData);
|
||||
// [this.oldData, newData] = equilizeNoOfElements(this.oldData, newData);
|
||||
|
||||
let newPos = newData.map(d => d.end);
|
||||
let newLabels = newData.map(d => d.label);
|
||||
let newStarts = newData.map(d => d.start);
|
||||
// let newPos = newData.map(d => d.end);
|
||||
// let newLabels = newData.map(d => d.label);
|
||||
// let newStarts = newData.map(d => d.start);
|
||||
|
||||
let oldPos = this.oldData.map(d => d.end);
|
||||
let oldLabels = this.oldData.map(d => d.label);
|
||||
let oldStarts = this.oldData.map(d => d.start);
|
||||
// let oldPos = this.oldData.map(d => d.end);
|
||||
// let oldLabels = this.oldData.map(d => d.label);
|
||||
// let oldStarts = this.oldData.map(d => d.start);
|
||||
|
||||
this.render(oldPos.map((pos, i) => {
|
||||
return {
|
||||
start: oldStarts[i],
|
||||
end: oldPos[i],
|
||||
label: newLabels[i]
|
||||
}
|
||||
}));
|
||||
// this.render(oldPos.map((pos, i) => {
|
||||
// return {
|
||||
// start: oldStarts[i],
|
||||
// end: oldPos[i],
|
||||
// label: newLabels[i]
|
||||
// }
|
||||
// }));
|
||||
|
||||
let animateElements = [];
|
||||
// let animateElements = [];
|
||||
|
||||
this.store.map((rectGroup, i) => {
|
||||
animateElements = animateElements.concat(animateRegion(
|
||||
rectGroup, newStarts[i], newPos[i], oldPos[i]
|
||||
));
|
||||
});
|
||||
// this.store.map((rectGroup, i) => {
|
||||
// animateElements = animateElements.concat(animateRegion(
|
||||
// rectGroup, newStarts[i], newPos[i], oldPos[i]
|
||||
// ));
|
||||
// });
|
||||
|
||||
return animateElements;
|
||||
// return animateElements;
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@ -1,4 +1,6 @@
|
||||
export const Y_AXIS_MARGIN = 60;
|
||||
|
||||
export const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||
export const DEFAULT_AXIS_CHART_TYPE = 'line';
|
||||
export const DEFAULT_AXIS_CHART_TYPE = 'line';
|
||||
export const AXIS_DATASET_CHART_TYPES = ['line', 'bar'];
|
||||
export const BAR_CHART_SPACE_RATIO = 0.5;
|
||||
@ -2,15 +2,9 @@ import { fillArray } from './helpers';
|
||||
|
||||
export function getBarHeightAndYAttr(yTop, zeroLine) {
|
||||
let height, y;
|
||||
if (yTop <= zeroLine) {
|
||||
if (yTop < zeroLine) {
|
||||
height = zeroLine - yTop;
|
||||
y = yTop;
|
||||
|
||||
// In case of invisible bars
|
||||
if(height === 0) {
|
||||
height = totalHeight * MIN_BAR_PERCENT_HEIGHT;
|
||||
y -= height;
|
||||
}
|
||||
} else {
|
||||
height = yTop - zeroLine;
|
||||
y = zeroLine;
|
||||
|
||||
@ -360,6 +360,37 @@ export function yRegion(y1, y2, width, label) {
|
||||
return region;
|
||||
}
|
||||
|
||||
export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={}) {
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine);
|
||||
// console.log(yTop, meta.zeroLine, y, offset);
|
||||
|
||||
let rect = createSVG('rect', {
|
||||
className: `bar mini`,
|
||||
style: `fill: ${color}`,
|
||||
'data-point-index': index,
|
||||
x: x - meta.barsWidth/2,
|
||||
y: y - offset,
|
||||
width: width,
|
||||
height: height || meta.minHeight
|
||||
});
|
||||
|
||||
if(!label && !label.length) {
|
||||
return rect;
|
||||
} else {
|
||||
let text = createSVG('text', {
|
||||
className: 'data-point-value',
|
||||
x: x,
|
||||
y: y - offset,
|
||||
dy: (FONT_SIZE / 2 * -1) + 'px',
|
||||
'font-size': FONT_SIZE + 'px',
|
||||
'text-anchor': 'middle',
|
||||
innerHTML: label
|
||||
});
|
||||
|
||||
return wrapInSVGGroup([rect, text]);
|
||||
}
|
||||
}
|
||||
|
||||
export class AxisChartRenderer {
|
||||
constructor(state) {
|
||||
this.refreshState(state);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { floatTwo } from './helpers';
|
||||
|
||||
function normalize(x) {
|
||||
// Calculates mantissa and exponent of a number
|
||||
// Returns normalized number and exponent
|
||||
@ -194,6 +196,10 @@ export function getValueRange(orderedArray) {
|
||||
return orderedArray[orderedArray.length-1] - orderedArray[0];
|
||||
}
|
||||
|
||||
export function scale(val, yAxis) {
|
||||
return floatTwo(yAxis.zeroLine - val * yAxis.scaleMultiplier)
|
||||
}
|
||||
|
||||
export function calcDistribution(values, distributionSize) {
|
||||
// Assume non-negative values,
|
||||
// implying distribution minimum at zero
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user