Working stacked bars
This commit is contained in:
parent
82f3446a43
commit
df15885135
165
dist/frappe-charts.esm.js
vendored
165
dist/frappe-charts.esm.js
vendored
@ -232,9 +232,7 @@ function getStringWidth(string, charWidth) {
|
||||
return (string+"").length * charWidth;
|
||||
}
|
||||
|
||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||
|
||||
function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||
function getBarHeightAndYAttr(yTop, zeroLine) {
|
||||
let height, y;
|
||||
if (yTop <= zeroLine) {
|
||||
height = zeroLine - yTop;
|
||||
@ -248,11 +246,6 @@ function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||
} else {
|
||||
height = yTop - zeroLine;
|
||||
y = zeroLine;
|
||||
|
||||
// In case of invisible bars
|
||||
if(height === 0) {
|
||||
height = totalHeight * MIN_BAR_PERCENT_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
return [height, y];
|
||||
@ -529,7 +522,6 @@ class AxisChartRenderer {
|
||||
if(!options.pos) options.pos = 'bottom';
|
||||
if(!options.offset) options.offset = 0;
|
||||
if(!options.mode) options.mode = this.xAxisMode;
|
||||
console.log(this.xAxisMode);
|
||||
if(!options.stroke) options.stroke = BASE_LINE_COLOR;
|
||||
if(!options.className) options.className = '';
|
||||
|
||||
@ -1174,6 +1166,13 @@ class BaseChart {
|
||||
);
|
||||
this.svgDefs = makeSVGDefs(this.svg);
|
||||
|
||||
// I wish !!!
|
||||
// this.svg = makeSVGGroup(
|
||||
// svgContainer,
|
||||
// 'flipped-coord-system',
|
||||
// `translate(0, ${this.baseHeight}) scale(1, -1)`
|
||||
// );
|
||||
|
||||
this.drawArea = makeSVGGroup(
|
||||
this.svg,
|
||||
this.type + '-chart',
|
||||
@ -1266,12 +1265,18 @@ class ChartComponent {
|
||||
constructor({
|
||||
layerClass = '',
|
||||
layerTransform = '',
|
||||
preMake,
|
||||
make,
|
||||
postMake,
|
||||
animate
|
||||
}) {
|
||||
this.layerClass = layerClass;
|
||||
this.layerTransform = layerTransform;
|
||||
|
||||
this.preMake = preMake;
|
||||
this.make = make;
|
||||
this.postMake = postMake;
|
||||
|
||||
this.animate = animate;
|
||||
|
||||
this.layer = undefined;
|
||||
@ -1281,12 +1286,15 @@ class ChartComponent {
|
||||
refresh(args) {}
|
||||
|
||||
render() {
|
||||
this.preMake && this.preMake();
|
||||
this.store = this.make();
|
||||
|
||||
this.layer.textContent = '';
|
||||
this.store.forEach(element => {
|
||||
this.layer.appendChild(element);
|
||||
});
|
||||
|
||||
this.postMake && this.postMake(this.store, this.layer);
|
||||
}
|
||||
|
||||
setupParent(parent) {
|
||||
@ -1302,17 +1310,23 @@ class ChartComponent {
|
||||
}
|
||||
}
|
||||
|
||||
const MIN_BAR_PERCENT_HEIGHT$1 = 0.01;
|
||||
|
||||
class AxisChartController {
|
||||
constructor(meta) {
|
||||
// TODO: make configurable passing args
|
||||
this.refreshMeta(meta);
|
||||
this.meta = meta || {};
|
||||
this.setupArgs();
|
||||
}
|
||||
|
||||
setupArgs() {}
|
||||
setupArgs() {
|
||||
this.consts = {};
|
||||
}
|
||||
|
||||
setup() {}
|
||||
|
||||
refreshMeta(meta) {
|
||||
this.meta = meta || {};
|
||||
this.meta = Object.assign((this.meta || {}), meta);
|
||||
}
|
||||
|
||||
draw() {}
|
||||
@ -1327,39 +1341,40 @@ class BarChartController extends AxisChartController {
|
||||
}
|
||||
|
||||
setupArgs() {
|
||||
this.args = {
|
||||
this.consts = {
|
||||
spaceRatio: 0.5,
|
||||
minHeight: this.meta.totalHeight * MIN_BAR_PERCENT_HEIGHT$1
|
||||
};
|
||||
}
|
||||
|
||||
draw(x, yTop, color, index, datasetIndex, noOfDatasets) {
|
||||
let totalWidth = this.meta.unitWidth - this.meta.unitWidth * this.args.spaceRatio;
|
||||
let startX = x - totalWidth/2;
|
||||
refreshMeta(meta) {
|
||||
if(meta) {
|
||||
super.refreshMeta(meta);
|
||||
}
|
||||
let m = this.meta;
|
||||
this.consts.barsWidth = m.unitWidth - m.unitWidth * this.consts.spaceRatio;
|
||||
|
||||
// temp commented
|
||||
// let width = totalWidth / noOfDatasets;
|
||||
// let currentX = startX + width * datasetIndex;
|
||||
this.consts.width = this.consts.barsWidth / (m.options && m.options.stacked
|
||||
? m.options.stacked : m.noOfDatasets);
|
||||
}
|
||||
|
||||
// temp
|
||||
let width = totalWidth;
|
||||
let currentX = startX;
|
||||
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
|
||||
draw(x, yTop, color, index, offset=0) {
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine);
|
||||
|
||||
return createSVG('rect', {
|
||||
className: `bar mini`,
|
||||
style: `fill: ${color}`,
|
||||
'data-point-index': index,
|
||||
x: currentX,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height
|
||||
x: x - this.consts.barsWidth/2,
|
||||
y: y - offset,
|
||||
width: this.consts.width,
|
||||
height: height || this.consts.minHeight
|
||||
});
|
||||
}
|
||||
|
||||
animate(bar, x, yTop, index, noOfDatasets) {
|
||||
let start = x - this.meta.avgUnitWidth/4;
|
||||
let width = (this.meta.avgUnitWidth/2)/noOfDatasets;
|
||||
let start = x - this.meta.unitWidth/4;
|
||||
let width = (this.meta.unitWidth/2)/noOfDatasets;
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
|
||||
|
||||
x = start + (width * index);
|
||||
@ -1375,8 +1390,7 @@ class LineChartController extends AxisChartController {
|
||||
}
|
||||
|
||||
setupArgs() {
|
||||
console.log(this);
|
||||
this.args = {
|
||||
this.consts = {
|
||||
radius: this.meta.dotSize || 4
|
||||
};
|
||||
}
|
||||
@ -1387,7 +1401,7 @@ class LineChartController extends AxisChartController {
|
||||
'data-point-index': index,
|
||||
cx: x,
|
||||
cy: y,
|
||||
r: this.args.radius
|
||||
r: this.consts.radius
|
||||
});
|
||||
}
|
||||
|
||||
@ -1703,7 +1717,9 @@ class AxisChart extends BaseChart {
|
||||
this.isSeries = args.isSeries;
|
||||
this.formatTooltipY = args.formatTooltipY;
|
||||
this.formatTooltipX = args.formatTooltipX;
|
||||
this.unitType = args.unitType || 'line';
|
||||
this.barOptions = args.barOptions;
|
||||
this.lineOptions = args.lineOptions;
|
||||
this.type = args.type || 'line';
|
||||
|
||||
this.setupUnitRenderer();
|
||||
|
||||
@ -1722,6 +1738,7 @@ class AxisChart extends BaseChart {
|
||||
preSetup() {}
|
||||
|
||||
setupUnitRenderer() {
|
||||
// TODO: this is empty
|
||||
let options = this.rawChartArgs.options;
|
||||
this.unitRenderers = {
|
||||
bar: new BarChartController(options),
|
||||
@ -1752,7 +1769,7 @@ class AxisChart extends BaseChart {
|
||||
|
||||
this.data.datasets.map(d => {
|
||||
if(!d.chartType ) {
|
||||
d.chartType = this.unitType;
|
||||
d.chartType = this.type;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1852,17 +1869,29 @@ class AxisChart extends BaseChart {
|
||||
calcYUnits() {
|
||||
let s = this.state;
|
||||
s.datasets.map(d => {
|
||||
d.positions = d.values.map(val => floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
d.positions = d.values.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
s.datasets.map((d, i) => {
|
||||
d.cumulativePositions = d.cumulativeYs.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
calcYMaximums() {
|
||||
let s = this.state;
|
||||
s.yUnitMinimums = new Array(s.datasetLength).fill(9999);
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativePositions;
|
||||
return;
|
||||
}
|
||||
s.yExtremes = new Array(s.datasetLength).fill(9999);
|
||||
s.datasets.map((d, i) => {
|
||||
d.positions.map((pos, j) => {
|
||||
if(pos < s.yUnitMinimums[j]) {
|
||||
s.yUnitMinimums[j] = pos;
|
||||
if(pos < s.yExtremes[j]) {
|
||||
s.yExtremes[j] = pos;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -1899,7 +1928,19 @@ class AxisChart extends BaseChart {
|
||||
|
||||
getAllYValues() {
|
||||
// TODO: yMarkers, regions, sums, every Y value ever
|
||||
return [].concat(...this.state.datasets.map(d => d.values));
|
||||
|
||||
let key = 'values';
|
||||
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
key = 'cumulativeYs';
|
||||
let cumulative = new Array(this.state.datasetLength).fill(0);
|
||||
this.state.datasets.map((d, i) => {
|
||||
let values = this.state.datasets[i].values;
|
||||
d[key] = cumulative = cumulative.map((c, i) => c + values[i]);
|
||||
});
|
||||
}
|
||||
|
||||
return [].concat(...this.state.datasets.map(d => d[key]));
|
||||
}
|
||||
|
||||
calcIntermedState() {
|
||||
@ -2011,31 +2052,50 @@ class AxisChart extends BaseChart {
|
||||
if(d.chartType === 'line') {
|
||||
dataUnitsComponents.push(this.getPathComponent(d, index));
|
||||
}
|
||||
console.log(this.unitRenderers[d.chartType], d.chartType);
|
||||
|
||||
let renderer = this.unitRenderers[d.chartType];
|
||||
dataUnitsComponents.push(this.getDataUnitComponent(
|
||||
d, index, this.unitRenderers[d.chartType]
|
||||
index, renderer
|
||||
));
|
||||
});
|
||||
return dataUnitsComponents;
|
||||
}
|
||||
|
||||
getDataUnitComponent(d, index, unitRenderer) {
|
||||
getDataUnitComponent(index, unitRenderer) {
|
||||
return new ChartComponent({
|
||||
layerClass: 'dataset-units dataset-' + index,
|
||||
preMake: () => { },
|
||||
make: () => {
|
||||
let d = this.state.datasets[index];
|
||||
|
||||
console.log('d.positions', d.positions);
|
||||
console.log('d.cumulativePositions', d.cumulativePositions);
|
||||
console.log('d.cumulativeYs', d.cumulativeYs);
|
||||
|
||||
return d.positions.map((y, j) => {
|
||||
return unitRenderer.draw(
|
||||
this.state.xAxisPositions[j],
|
||||
y,
|
||||
this.colors[index],
|
||||
j,
|
||||
index,
|
||||
this.state.noOfDatasets
|
||||
j
|
||||
,
|
||||
y - (d.cumulativePositions ? d.cumulativePositions[j] : y)
|
||||
);
|
||||
});
|
||||
},
|
||||
postMake: (store, layer) => {
|
||||
let translate_layer = () => {
|
||||
layer.setAttribute('transform', `translate(${unitRenderer.consts.width * index}, 0)`);
|
||||
};
|
||||
|
||||
// let d = this.state.datasets[index];
|
||||
|
||||
if(this.type === 'bar' && (!this.barOptions
|
||||
|| !this.barOptions.stacked)) {
|
||||
|
||||
translate_layer();
|
||||
}
|
||||
},
|
||||
animate: (svgUnits) => {
|
||||
// have been updated in axis render;
|
||||
let newX = this.state.xAxisPositions;
|
||||
@ -2181,9 +2241,13 @@ class AxisChart extends BaseChart {
|
||||
totalWidth: this.width,
|
||||
zeroLine: this.state.zeroLine,
|
||||
unitWidth: this.state.unitWidth,
|
||||
noOfDatasets: this.state.noOfDatasets,
|
||||
};
|
||||
|
||||
meta = Object.assign(meta, this.rawChartArgs.options);
|
||||
|
||||
Object.keys(this.unitRenderers).map(key => {
|
||||
meta.options = this[key + 'Options'];
|
||||
this.unitRenderers[key].refreshMeta(meta);
|
||||
});
|
||||
}
|
||||
@ -2205,7 +2269,7 @@ class AxisChart extends BaseChart {
|
||||
|
||||
mapTooltipXPosition(relX) {
|
||||
let s = this.state;
|
||||
if(!s.yUnitMinimums) return;
|
||||
if(!s.yExtremes) return;
|
||||
|
||||
let titles = s.xAxisLabels;
|
||||
if(this.formatTooltipX && this.formatTooltipX(titles[0])) {
|
||||
@ -2219,7 +2283,7 @@ class AxisChart extends BaseChart {
|
||||
// let delta = i === 0 ? s.unitWidth : xVal - s.xAxisPositions[i-1];
|
||||
if(relX > xVal - s.unitWidth/2) {
|
||||
let x = xVal + this.translateXLeft;
|
||||
let y = s.yUnitMinimums[i] + this.translateY;
|
||||
let y = s.yExtremes[i] + this.translateY;
|
||||
|
||||
let values = s.datasets.map((set, j) => {
|
||||
return {
|
||||
@ -3138,11 +3202,12 @@ const chartTypes = {
|
||||
};
|
||||
|
||||
function getChartByType(chartType = 'line', options) {
|
||||
debugger;
|
||||
if(chartType === 'line') {
|
||||
options.unitType = 'line';
|
||||
options.type = 'line';
|
||||
return new AxisChart(options);
|
||||
} else if (chartType === 'bar') {
|
||||
options.unitType = 'bar';
|
||||
options.type = 'bar';
|
||||
return new AxisChart(options);
|
||||
}
|
||||
|
||||
|
||||
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
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
@ -119,12 +119,13 @@ let type_data = {
|
||||
name: "Another Set",
|
||||
values: [30, 50, -10, 15, 18, 32, 27, 14],
|
||||
axisPosition: 'right',
|
||||
chartType: 'line'
|
||||
chartType: 'bar'
|
||||
},
|
||||
// {
|
||||
// name: "Yet Another",
|
||||
// values: [15, 20, -3, -15, 58, 12, -17, 37]
|
||||
// }
|
||||
{
|
||||
name: "Yet Another",
|
||||
values: [15, 20, -3, -15, 58, 12, -17, 37],
|
||||
// chartType: 'line'
|
||||
}
|
||||
|
||||
// temp : Stacked
|
||||
// {
|
||||
@ -148,10 +149,13 @@ let type_chart = new Chart({
|
||||
data: type_data,
|
||||
type: 'line',
|
||||
height: 250,
|
||||
colors: ['purple', 'magenta'],
|
||||
colors: ['purple', 'magenta', 'light-blue'],
|
||||
isSeries: 1,
|
||||
xAxisMode: 'tick',
|
||||
yAxisMode: 'span',
|
||||
barOptions: {
|
||||
// stacked: 1
|
||||
}
|
||||
// formatTooltipX: d => (d + '').toUpperCase(),
|
||||
// formatTooltipY: d => d + ' pts'
|
||||
});
|
||||
@ -202,8 +206,10 @@ let plot_chart_args = {
|
||||
height: 250,
|
||||
colors: ['blue'],
|
||||
isSeries: 1,
|
||||
showDots: 0,
|
||||
heatline: 1,
|
||||
lineOptions: {
|
||||
showDots: 0,
|
||||
heatline: 1,
|
||||
},
|
||||
xAxisMode: 'tick',
|
||||
yAxisMode: 'span'
|
||||
};
|
||||
@ -377,10 +383,6 @@ let aggr_data = {
|
||||
},
|
||||
{
|
||||
"values": [25, 50, -10, 15, 18, 32, 27],
|
||||
"unitArgs": {
|
||||
type: 'dot',
|
||||
args: { radius: 4 }
|
||||
},
|
||||
}
|
||||
]
|
||||
};
|
||||
@ -391,6 +393,9 @@ let aggr_chart = new Chart({
|
||||
type: 'bar',
|
||||
height: 250,
|
||||
colors: ['light-green', 'blue'],
|
||||
barOptions: {
|
||||
stacked: 1
|
||||
}
|
||||
});
|
||||
|
||||
document.querySelector('[data-aggregation="sums"]').addEventListener("click", (e) => {
|
||||
|
||||
@ -30,11 +30,12 @@ const chartTypes = {
|
||||
};
|
||||
|
||||
function getChartByType(chartType = 'line', options) {
|
||||
debugger;
|
||||
if(chartType === 'line') {
|
||||
options.unitType = 'line';
|
||||
options.type = 'line';
|
||||
return new AxisChart(options);
|
||||
} else if (chartType === 'bar') {
|
||||
options.unitType = 'bar';
|
||||
options.type = 'bar';
|
||||
return new AxisChart(options);
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,9 @@ export default class AxisChart extends BaseChart {
|
||||
this.isSeries = args.isSeries;
|
||||
this.formatTooltipY = args.formatTooltipY;
|
||||
this.formatTooltipX = args.formatTooltipX;
|
||||
this.unitType = args.unitType || 'line';
|
||||
this.barOptions = args.barOptions;
|
||||
this.lineOptions = args.lineOptions;
|
||||
this.type = args.type || 'line';
|
||||
|
||||
this.setupUnitRenderer();
|
||||
|
||||
@ -35,6 +37,7 @@ export default class AxisChart extends BaseChart {
|
||||
preSetup() {}
|
||||
|
||||
setupUnitRenderer() {
|
||||
// TODO: this is empty
|
||||
let options = this.rawChartArgs.options;
|
||||
this.unitRenderers = {
|
||||
bar: new BarChartController(options),
|
||||
@ -65,7 +68,7 @@ export default class AxisChart extends BaseChart {
|
||||
|
||||
this.data.datasets.map(d => {
|
||||
if(!d.chartType ) {
|
||||
d.chartType = this.unitType;
|
||||
d.chartType = this.type;
|
||||
}
|
||||
});
|
||||
|
||||
@ -165,17 +168,29 @@ export default class AxisChart extends BaseChart {
|
||||
calcYUnits() {
|
||||
let s = this.state;
|
||||
s.datasets.map(d => {
|
||||
d.positions = d.values.map(val => floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
d.positions = d.values.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
s.datasets.map((d, i) => {
|
||||
d.cumulativePositions = d.cumulativeYs.map(val =>
|
||||
floatTwo(s.yAxis.zeroLine - val * s.yAxis.scaleMultiplier));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
calcYMaximums() {
|
||||
let s = this.state;
|
||||
s.yUnitMinimums = new Array(s.datasetLength).fill(9999);
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativePositions;
|
||||
return;
|
||||
}
|
||||
s.yExtremes = new Array(s.datasetLength).fill(9999);
|
||||
s.datasets.map((d, i) => {
|
||||
d.positions.map((pos, j) => {
|
||||
if(pos < s.yUnitMinimums[j]) {
|
||||
s.yUnitMinimums[j] = pos;
|
||||
if(pos < s.yExtremes[j]) {
|
||||
s.yExtremes[j] = pos;
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -212,7 +227,19 @@ export default class AxisChart extends BaseChart {
|
||||
|
||||
getAllYValues() {
|
||||
// TODO: yMarkers, regions, sums, every Y value ever
|
||||
return [].concat(...this.state.datasets.map(d => d.values));
|
||||
|
||||
let key = 'values';
|
||||
|
||||
if(this.barOptions && this.barOptions.stacked) {
|
||||
key = 'cumulativeYs';
|
||||
let cumulative = new Array(this.state.datasetLength).fill(0);
|
||||
this.state.datasets.map((d, i) => {
|
||||
let values = this.state.datasets[i].values;
|
||||
d[key] = cumulative = cumulative.map((c, i) => c + values[i]);
|
||||
});
|
||||
}
|
||||
|
||||
return [].concat(...this.state.datasets.map(d => d[key]));
|
||||
}
|
||||
|
||||
calcIntermedState() {
|
||||
@ -324,31 +351,50 @@ export default class AxisChart extends BaseChart {
|
||||
if(d.chartType === 'line') {
|
||||
dataUnitsComponents.push(this.getPathComponent(d, index));
|
||||
}
|
||||
console.log(this.unitRenderers[d.chartType], d.chartType);
|
||||
|
||||
let renderer = this.unitRenderers[d.chartType];
|
||||
dataUnitsComponents.push(this.getDataUnitComponent(
|
||||
d, index, this.unitRenderers[d.chartType]
|
||||
index, renderer
|
||||
));
|
||||
});
|
||||
return dataUnitsComponents;
|
||||
}
|
||||
|
||||
getDataUnitComponent(d, index, unitRenderer) {
|
||||
getDataUnitComponent(index, unitRenderer) {
|
||||
return new ChartComponent({
|
||||
layerClass: 'dataset-units dataset-' + index,
|
||||
preMake: () => { },
|
||||
make: () => {
|
||||
let d = this.state.datasets[index];
|
||||
|
||||
console.log('d.positions', d.positions);
|
||||
console.log('d.cumulativePositions', d.cumulativePositions);
|
||||
console.log('d.cumulativeYs', d.cumulativeYs);
|
||||
|
||||
return d.positions.map((y, j) => {
|
||||
return unitRenderer.draw(
|
||||
this.state.xAxisPositions[j],
|
||||
y,
|
||||
this.colors[index],
|
||||
j,
|
||||
index,
|
||||
this.state.noOfDatasets
|
||||
j
|
||||
,
|
||||
y - (d.cumulativePositions ? d.cumulativePositions[j] : y)
|
||||
);
|
||||
});
|
||||
},
|
||||
postMake: (store, layer) => {
|
||||
let translate_layer = () => {
|
||||
layer.setAttribute('transform', `translate(${unitRenderer.consts.width * index}, 0)`);
|
||||
}
|
||||
|
||||
// let d = this.state.datasets[index];
|
||||
|
||||
if(this.type === 'bar' && (!this.barOptions
|
||||
|| !this.barOptions.stacked)) {
|
||||
|
||||
translate_layer();
|
||||
}
|
||||
},
|
||||
animate: (svgUnits) => {
|
||||
// have been updated in axis render;
|
||||
let newX = this.state.xAxisPositions;
|
||||
@ -494,9 +540,13 @@ export default class AxisChart extends BaseChart {
|
||||
totalWidth: this.width,
|
||||
zeroLine: this.state.zeroLine,
|
||||
unitWidth: this.state.unitWidth,
|
||||
noOfDatasets: this.state.noOfDatasets,
|
||||
};
|
||||
|
||||
meta = Object.assign(meta, this.rawChartArgs.options);
|
||||
|
||||
Object.keys(this.unitRenderers).map(key => {
|
||||
meta.options = this[key + 'Options'];
|
||||
this.unitRenderers[key].refreshMeta(meta);
|
||||
});
|
||||
}
|
||||
@ -518,7 +568,7 @@ export default class AxisChart extends BaseChart {
|
||||
|
||||
mapTooltipXPosition(relX) {
|
||||
let s = this.state;
|
||||
if(!s.yUnitMinimums) return;
|
||||
if(!s.yExtremes) return;
|
||||
|
||||
let titles = s.xAxisLabels;
|
||||
if(this.formatTooltipX && this.formatTooltipX(titles[0])) {
|
||||
@ -532,7 +582,7 @@ export default class AxisChart extends BaseChart {
|
||||
// let delta = i === 0 ? s.unitWidth : xVal - s.xAxisPositions[i-1];
|
||||
if(relX > xVal - s.unitWidth/2) {
|
||||
let x = xVal + this.translateXLeft;
|
||||
let y = s.yUnitMinimums[i] + this.translateY;
|
||||
let y = s.yExtremes[i] + this.translateY;
|
||||
|
||||
let values = s.datasets.map((set, j) => {
|
||||
return {
|
||||
|
||||
@ -236,6 +236,13 @@ export default class BaseChart {
|
||||
);
|
||||
this.svgDefs = makeSVGDefs(this.svg);
|
||||
|
||||
// I wish !!!
|
||||
// this.svg = makeSVGGroup(
|
||||
// svgContainer,
|
||||
// 'flipped-coord-system',
|
||||
// `translate(0, ${this.baseHeight}) scale(1, -1)`
|
||||
// );
|
||||
|
||||
this.drawArea = makeSVGGroup(
|
||||
this.svg,
|
||||
this.type + '-chart',
|
||||
|
||||
@ -2,17 +2,23 @@ import { getBarHeightAndYAttr } from '../utils/draw-utils';
|
||||
import { createSVG, makePath, makeGradient } from '../utils/draw';
|
||||
import { STD_EASING, UNIT_ANIM_DUR, MARKER_LINE_ANIM_DUR, PATH_ANIM_DUR } from '../utils/animate';
|
||||
|
||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||
|
||||
class AxisChartController {
|
||||
constructor(meta) {
|
||||
// TODO: make configurable passing args
|
||||
this.refreshMeta(meta);
|
||||
this.meta = meta || {};
|
||||
this.setupArgs();
|
||||
}
|
||||
|
||||
setupArgs() {}
|
||||
setupArgs() {
|
||||
this.consts = {};
|
||||
}
|
||||
|
||||
setup() {}
|
||||
|
||||
refreshMeta(meta) {
|
||||
this.meta = meta || {};
|
||||
this.meta = Object.assign((this.meta || {}), meta);
|
||||
}
|
||||
|
||||
draw() {}
|
||||
@ -24,15 +30,13 @@ export class AxisController extends AxisChartController {
|
||||
super(meta);
|
||||
}
|
||||
|
||||
setupArgs() {}
|
||||
|
||||
draw(x, y, color, index) {
|
||||
return createSVG('circle', {
|
||||
style: `fill: ${color}`,
|
||||
'data-point-index': index,
|
||||
cx: x,
|
||||
cy: y,
|
||||
r: this.args.radius
|
||||
r: this.consts.radius
|
||||
});
|
||||
}
|
||||
|
||||
@ -48,39 +52,40 @@ export class BarChartController extends AxisChartController {
|
||||
}
|
||||
|
||||
setupArgs() {
|
||||
this.args = {
|
||||
this.consts = {
|
||||
spaceRatio: 0.5,
|
||||
minHeight: this.meta.totalHeight * MIN_BAR_PERCENT_HEIGHT
|
||||
};
|
||||
}
|
||||
|
||||
draw(x, yTop, color, index, datasetIndex, noOfDatasets) {
|
||||
let totalWidth = this.meta.unitWidth - this.meta.unitWidth * this.args.spaceRatio;
|
||||
let startX = x - totalWidth/2;
|
||||
refreshMeta(meta) {
|
||||
if(meta) {
|
||||
super.refreshMeta(meta);
|
||||
}
|
||||
let m = this.meta;
|
||||
this.consts.barsWidth = m.unitWidth - m.unitWidth * this.consts.spaceRatio;
|
||||
|
||||
// temp commented
|
||||
// let width = totalWidth / noOfDatasets;
|
||||
// let currentX = startX + width * datasetIndex;
|
||||
this.consts.width = this.consts.barsWidth / (m.options && m.options.stacked
|
||||
? m.options.stacked : m.noOfDatasets);
|
||||
}
|
||||
|
||||
// temp
|
||||
let width = totalWidth;
|
||||
let currentX = startX;
|
||||
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
|
||||
draw(x, yTop, color, index, offset=0) {
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine);
|
||||
|
||||
return createSVG('rect', {
|
||||
className: `bar mini`,
|
||||
style: `fill: ${color}`,
|
||||
'data-point-index': index,
|
||||
x: currentX,
|
||||
y: y,
|
||||
width: width,
|
||||
height: height
|
||||
x: x - this.consts.barsWidth/2,
|
||||
y: y - offset,
|
||||
width: this.consts.width,
|
||||
height: height || this.consts.minHeight
|
||||
});
|
||||
}
|
||||
|
||||
animate(bar, x, yTop, index, noOfDatasets) {
|
||||
let start = x - this.meta.avgUnitWidth/4;
|
||||
let width = (this.meta.avgUnitWidth/2)/noOfDatasets;
|
||||
let start = x - this.meta.unitWidth/4;
|
||||
let width = (this.meta.unitWidth/2)/noOfDatasets;
|
||||
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
|
||||
|
||||
x = start + (width * index);
|
||||
@ -96,8 +101,7 @@ export class LineChartController extends AxisChartController {
|
||||
}
|
||||
|
||||
setupArgs() {
|
||||
console.log(this);
|
||||
this.args = {
|
||||
this.consts = {
|
||||
radius: this.meta.dotSize || 4
|
||||
};
|
||||
}
|
||||
@ -108,7 +112,7 @@ export class LineChartController extends AxisChartController {
|
||||
'data-point-index': index,
|
||||
cx: x,
|
||||
cy: y,
|
||||
r: this.args.radius
|
||||
r: this.consts.radius
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@ -4,12 +4,18 @@ export class ChartComponent {
|
||||
constructor({
|
||||
layerClass = '',
|
||||
layerTransform = '',
|
||||
preMake,
|
||||
make,
|
||||
postMake,
|
||||
animate
|
||||
}) {
|
||||
this.layerClass = layerClass;
|
||||
this.layerTransform = layerTransform;
|
||||
|
||||
this.preMake = preMake;
|
||||
this.make = make;
|
||||
this.postMake = postMake;
|
||||
|
||||
this.animate = animate;
|
||||
|
||||
this.layer = undefined;
|
||||
@ -19,12 +25,15 @@ export class ChartComponent {
|
||||
refresh(args) {}
|
||||
|
||||
render() {
|
||||
this.preMake && this.preMake();
|
||||
this.store = this.make();
|
||||
|
||||
this.layer.textContent = '';
|
||||
this.store.forEach(element => {
|
||||
this.layer.appendChild(element);
|
||||
});
|
||||
|
||||
this.postMake && this.postMake(this.store, this.layer);
|
||||
}
|
||||
|
||||
setupParent(parent) {
|
||||
|
||||
@ -1,2 +0,0 @@
|
||||
import { getBarHeightAndYAttr } from '../utils/draw-utils';
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import { fillArray } from './helpers';
|
||||
|
||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||
|
||||
export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||
export function getBarHeightAndYAttr(yTop, zeroLine) {
|
||||
let height, y;
|
||||
if (yTop <= zeroLine) {
|
||||
height = zeroLine - yTop;
|
||||
@ -16,11 +14,6 @@ export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||
} else {
|
||||
height = yTop - zeroLine;
|
||||
y = zeroLine;
|
||||
|
||||
// In case of invisible bars
|
||||
if(height === 0) {
|
||||
height = totalHeight * MIN_BAR_PERCENT_HEIGHT;
|
||||
}
|
||||
}
|
||||
|
||||
return [height, y];
|
||||
|
||||
@ -236,7 +236,6 @@ export class AxisChartRenderer {
|
||||
if(!options.pos) options.pos = 'bottom';
|
||||
if(!options.offset) options.offset = 0;
|
||||
if(!options.mode) options.mode = this.xAxisMode;
|
||||
console.log(this.xAxisMode);
|
||||
if(!options.stroke) options.stroke = BASE_LINE_COLOR;
|
||||
if(!options.className) options.className = '';
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user