Working stacked bars

This commit is contained in:
Prateeksha Singh 2018-02-20 00:27:05 +05:30
parent 82f3446a43
commit df15885135
14 changed files with 252 additions and 121 deletions

View File

@ -232,9 +232,7 @@ function getStringWidth(string, charWidth) {
return (string+"").length * charWidth; return (string+"").length * charWidth;
} }
const MIN_BAR_PERCENT_HEIGHT = 0.01; function getBarHeightAndYAttr(yTop, zeroLine) {
function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
let height, y; let height, y;
if (yTop <= zeroLine) { if (yTop <= zeroLine) {
height = zeroLine - yTop; height = zeroLine - yTop;
@ -248,11 +246,6 @@ function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
} else { } else {
height = yTop - zeroLine; height = yTop - zeroLine;
y = zeroLine; y = zeroLine;
// In case of invisible bars
if(height === 0) {
height = totalHeight * MIN_BAR_PERCENT_HEIGHT;
}
} }
return [height, y]; return [height, y];
@ -529,7 +522,6 @@ class AxisChartRenderer {
if(!options.pos) options.pos = 'bottom'; if(!options.pos) options.pos = 'bottom';
if(!options.offset) options.offset = 0; if(!options.offset) options.offset = 0;
if(!options.mode) options.mode = this.xAxisMode; if(!options.mode) options.mode = this.xAxisMode;
console.log(this.xAxisMode);
if(!options.stroke) options.stroke = BASE_LINE_COLOR; if(!options.stroke) options.stroke = BASE_LINE_COLOR;
if(!options.className) options.className = ''; if(!options.className) options.className = '';
@ -1174,6 +1166,13 @@ class BaseChart {
); );
this.svgDefs = makeSVGDefs(this.svg); 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.drawArea = makeSVGGroup(
this.svg, this.svg,
this.type + '-chart', this.type + '-chart',
@ -1266,12 +1265,18 @@ class ChartComponent {
constructor({ constructor({
layerClass = '', layerClass = '',
layerTransform = '', layerTransform = '',
preMake,
make, make,
postMake,
animate animate
}) { }) {
this.layerClass = layerClass; this.layerClass = layerClass;
this.layerTransform = layerTransform; this.layerTransform = layerTransform;
this.preMake = preMake;
this.make = make; this.make = make;
this.postMake = postMake;
this.animate = animate; this.animate = animate;
this.layer = undefined; this.layer = undefined;
@ -1281,12 +1286,15 @@ class ChartComponent {
refresh(args) {} refresh(args) {}
render() { render() {
this.preMake && this.preMake();
this.store = this.make(); this.store = this.make();
this.layer.textContent = ''; this.layer.textContent = '';
this.store.forEach(element => { this.store.forEach(element => {
this.layer.appendChild(element); this.layer.appendChild(element);
}); });
this.postMake && this.postMake(this.store, this.layer);
} }
setupParent(parent) { setupParent(parent) {
@ -1302,17 +1310,23 @@ class ChartComponent {
} }
} }
const MIN_BAR_PERCENT_HEIGHT$1 = 0.01;
class AxisChartController { class AxisChartController {
constructor(meta) { constructor(meta) {
// TODO: make configurable passing args // TODO: make configurable passing args
this.refreshMeta(meta); this.meta = meta || {};
this.setupArgs(); this.setupArgs();
} }
setupArgs() {} setupArgs() {
this.consts = {};
}
setup() {}
refreshMeta(meta) { refreshMeta(meta) {
this.meta = meta || {}; this.meta = Object.assign((this.meta || {}), meta);
} }
draw() {} draw() {}
@ -1327,39 +1341,40 @@ class BarChartController extends AxisChartController {
} }
setupArgs() { setupArgs() {
this.args = { this.consts = {
spaceRatio: 0.5, spaceRatio: 0.5,
minHeight: this.meta.totalHeight * MIN_BAR_PERCENT_HEIGHT$1
}; };
} }
draw(x, yTop, color, index, datasetIndex, noOfDatasets) { refreshMeta(meta) {
let totalWidth = this.meta.unitWidth - this.meta.unitWidth * this.args.spaceRatio; if(meta) {
let startX = x - totalWidth/2; super.refreshMeta(meta);
}
let m = this.meta;
this.consts.barsWidth = m.unitWidth - m.unitWidth * this.consts.spaceRatio;
// temp commented this.consts.width = this.consts.barsWidth / (m.options && m.options.stacked
// let width = totalWidth / noOfDatasets; ? m.options.stacked : m.noOfDatasets);
// let currentX = startX + width * datasetIndex; }
// temp draw(x, yTop, color, index, offset=0) {
let width = totalWidth; let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine);
let currentX = startX;
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
return createSVG('rect', { return createSVG('rect', {
className: `bar mini`, className: `bar mini`,
style: `fill: ${color}`, style: `fill: ${color}`,
'data-point-index': index, 'data-point-index': index,
x: currentX, x: x - this.consts.barsWidth/2,
y: y, y: y - offset,
width: width, width: this.consts.width,
height: height height: height || this.consts.minHeight
}); });
} }
animate(bar, x, yTop, index, noOfDatasets) { animate(bar, x, yTop, index, noOfDatasets) {
let start = x - this.meta.avgUnitWidth/4; let start = x - this.meta.unitWidth/4;
let width = (this.meta.avgUnitWidth/2)/noOfDatasets; let width = (this.meta.unitWidth/2)/noOfDatasets;
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight); let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
x = start + (width * index); x = start + (width * index);
@ -1375,8 +1390,7 @@ class LineChartController extends AxisChartController {
} }
setupArgs() { setupArgs() {
console.log(this); this.consts = {
this.args = {
radius: this.meta.dotSize || 4 radius: this.meta.dotSize || 4
}; };
} }
@ -1387,7 +1401,7 @@ class LineChartController extends AxisChartController {
'data-point-index': index, 'data-point-index': index,
cx: x, cx: x,
cy: y, cy: y,
r: this.args.radius r: this.consts.radius
}); });
} }
@ -1703,7 +1717,9 @@ class AxisChart extends BaseChart {
this.isSeries = args.isSeries; this.isSeries = args.isSeries;
this.formatTooltipY = args.formatTooltipY; this.formatTooltipY = args.formatTooltipY;
this.formatTooltipX = args.formatTooltipX; this.formatTooltipX = args.formatTooltipX;
this.unitType = args.unitType || 'line'; this.barOptions = args.barOptions;
this.lineOptions = args.lineOptions;
this.type = args.type || 'line';
this.setupUnitRenderer(); this.setupUnitRenderer();
@ -1722,6 +1738,7 @@ class AxisChart extends BaseChart {
preSetup() {} preSetup() {}
setupUnitRenderer() { setupUnitRenderer() {
// TODO: this is empty
let options = this.rawChartArgs.options; let options = this.rawChartArgs.options;
this.unitRenderers = { this.unitRenderers = {
bar: new BarChartController(options), bar: new BarChartController(options),
@ -1752,7 +1769,7 @@ class AxisChart extends BaseChart {
this.data.datasets.map(d => { this.data.datasets.map(d => {
if(!d.chartType ) { if(!d.chartType ) {
d.chartType = this.unitType; d.chartType = this.type;
} }
}); });
@ -1852,17 +1869,29 @@ class AxisChart extends BaseChart {
calcYUnits() { calcYUnits() {
let s = this.state; let s = this.state;
s.datasets.map(d => { 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() { calcYMaximums() {
let s = this.state; 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) => { s.datasets.map((d, i) => {
d.positions.map((pos, j) => { d.positions.map((pos, j) => {
if(pos < s.yUnitMinimums[j]) { if(pos < s.yExtremes[j]) {
s.yUnitMinimums[j] = pos; s.yExtremes[j] = pos;
} }
}); });
}); });
@ -1899,7 +1928,19 @@ class AxisChart extends BaseChart {
getAllYValues() { getAllYValues() {
// TODO: yMarkers, regions, sums, every Y value ever // 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() { calcIntermedState() {
@ -2011,31 +2052,50 @@ class AxisChart extends BaseChart {
if(d.chartType === 'line') { if(d.chartType === 'line') {
dataUnitsComponents.push(this.getPathComponent(d, index)); dataUnitsComponents.push(this.getPathComponent(d, index));
} }
console.log(this.unitRenderers[d.chartType], d.chartType);
let renderer = this.unitRenderers[d.chartType];
dataUnitsComponents.push(this.getDataUnitComponent( dataUnitsComponents.push(this.getDataUnitComponent(
d, index, this.unitRenderers[d.chartType] index, renderer
)); ));
}); });
return dataUnitsComponents; return dataUnitsComponents;
} }
getDataUnitComponent(d, index, unitRenderer) { getDataUnitComponent(index, unitRenderer) {
return new ChartComponent({ return new ChartComponent({
layerClass: 'dataset-units dataset-' + index, layerClass: 'dataset-units dataset-' + index,
preMake: () => { },
make: () => { make: () => {
let d = this.state.datasets[index]; 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 d.positions.map((y, j) => {
return unitRenderer.draw( return unitRenderer.draw(
this.state.xAxisPositions[j], this.state.xAxisPositions[j],
y, y,
this.colors[index], this.colors[index],
j, j
index, ,
this.state.noOfDatasets 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) => { animate: (svgUnits) => {
// have been updated in axis render; // have been updated in axis render;
let newX = this.state.xAxisPositions; let newX = this.state.xAxisPositions;
@ -2181,9 +2241,13 @@ class AxisChart extends BaseChart {
totalWidth: this.width, totalWidth: this.width,
zeroLine: this.state.zeroLine, zeroLine: this.state.zeroLine,
unitWidth: this.state.unitWidth, unitWidth: this.state.unitWidth,
noOfDatasets: this.state.noOfDatasets,
}; };
meta = Object.assign(meta, this.rawChartArgs.options);
Object.keys(this.unitRenderers).map(key => { Object.keys(this.unitRenderers).map(key => {
meta.options = this[key + 'Options'];
this.unitRenderers[key].refreshMeta(meta); this.unitRenderers[key].refreshMeta(meta);
}); });
} }
@ -2205,7 +2269,7 @@ class AxisChart extends BaseChart {
mapTooltipXPosition(relX) { mapTooltipXPosition(relX) {
let s = this.state; let s = this.state;
if(!s.yUnitMinimums) return; if(!s.yExtremes) return;
let titles = s.xAxisLabels; let titles = s.xAxisLabels;
if(this.formatTooltipX && this.formatTooltipX(titles[0])) { 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]; // let delta = i === 0 ? s.unitWidth : xVal - s.xAxisPositions[i-1];
if(relX > xVal - s.unitWidth/2) { if(relX > xVal - s.unitWidth/2) {
let x = xVal + this.translateXLeft; 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) => { let values = s.datasets.map((set, j) => {
return { return {
@ -3138,11 +3202,12 @@ const chartTypes = {
}; };
function getChartByType(chartType = 'line', options) { function getChartByType(chartType = 'line', options) {
debugger;
if(chartType === 'line') { if(chartType === 'line') {
options.unitType = 'line'; options.type = 'line';
return new AxisChart(options); return new AxisChart(options);
} else if (chartType === 'bar') { } else if (chartType === 'bar') {
options.unitType = 'bar'; options.type = 'bar';
return new AxisChart(options); return new AxisChart(options);
} }

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

@ -119,12 +119,13 @@ let type_data = {
name: "Another Set", name: "Another Set",
values: [30, 50, -10, 15, 18, 32, 27, 14], values: [30, 50, -10, 15, 18, 32, 27, 14],
axisPosition: 'right', axisPosition: 'right',
chartType: 'line' chartType: 'bar'
}, },
// { {
// name: "Yet Another", name: "Yet Another",
// values: [15, 20, -3, -15, 58, 12, -17, 37] values: [15, 20, -3, -15, 58, 12, -17, 37],
// } // chartType: 'line'
}
// temp : Stacked // temp : Stacked
// { // {
@ -148,10 +149,13 @@ let type_chart = new Chart({
data: type_data, data: type_data,
type: 'line', type: 'line',
height: 250, height: 250,
colors: ['purple', 'magenta'], colors: ['purple', 'magenta', 'light-blue'],
isSeries: 1, isSeries: 1,
xAxisMode: 'tick', xAxisMode: 'tick',
yAxisMode: 'span', yAxisMode: 'span',
barOptions: {
// stacked: 1
}
// formatTooltipX: d => (d + '').toUpperCase(), // formatTooltipX: d => (d + '').toUpperCase(),
// formatTooltipY: d => d + ' pts' // formatTooltipY: d => d + ' pts'
}); });
@ -202,8 +206,10 @@ let plot_chart_args = {
height: 250, height: 250,
colors: ['blue'], colors: ['blue'],
isSeries: 1, isSeries: 1,
showDots: 0, lineOptions: {
heatline: 1, showDots: 0,
heatline: 1,
},
xAxisMode: 'tick', xAxisMode: 'tick',
yAxisMode: 'span' yAxisMode: 'span'
}; };
@ -377,10 +383,6 @@ let aggr_data = {
}, },
{ {
"values": [25, 50, -10, 15, 18, 32, 27], "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', type: 'bar',
height: 250, height: 250,
colors: ['light-green', 'blue'], colors: ['light-green', 'blue'],
barOptions: {
stacked: 1
}
}); });
document.querySelector('[data-aggregation="sums"]').addEventListener("click", (e) => { document.querySelector('[data-aggregation="sums"]').addEventListener("click", (e) => {

View File

@ -30,11 +30,12 @@ const chartTypes = {
}; };
function getChartByType(chartType = 'line', options) { function getChartByType(chartType = 'line', options) {
debugger;
if(chartType === 'line') { if(chartType === 'line') {
options.unitType = 'line'; options.type = 'line';
return new AxisChart(options); return new AxisChart(options);
} else if (chartType === 'bar') { } else if (chartType === 'bar') {
options.unitType = 'bar'; options.type = 'bar';
return new AxisChart(options); return new AxisChart(options);
} }

View File

@ -16,7 +16,9 @@ export default class AxisChart extends BaseChart {
this.isSeries = args.isSeries; this.isSeries = args.isSeries;
this.formatTooltipY = args.formatTooltipY; this.formatTooltipY = args.formatTooltipY;
this.formatTooltipX = args.formatTooltipX; this.formatTooltipX = args.formatTooltipX;
this.unitType = args.unitType || 'line'; this.barOptions = args.barOptions;
this.lineOptions = args.lineOptions;
this.type = args.type || 'line';
this.setupUnitRenderer(); this.setupUnitRenderer();
@ -35,6 +37,7 @@ export default class AxisChart extends BaseChart {
preSetup() {} preSetup() {}
setupUnitRenderer() { setupUnitRenderer() {
// TODO: this is empty
let options = this.rawChartArgs.options; let options = this.rawChartArgs.options;
this.unitRenderers = { this.unitRenderers = {
bar: new BarChartController(options), bar: new BarChartController(options),
@ -65,7 +68,7 @@ export default class AxisChart extends BaseChart {
this.data.datasets.map(d => { this.data.datasets.map(d => {
if(!d.chartType ) { if(!d.chartType ) {
d.chartType = this.unitType; d.chartType = this.type;
} }
}); });
@ -165,17 +168,29 @@ export default class AxisChart extends BaseChart {
calcYUnits() { calcYUnits() {
let s = this.state; let s = this.state;
s.datasets.map(d => { 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() { calcYMaximums() {
let s = this.state; 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) => { s.datasets.map((d, i) => {
d.positions.map((pos, j) => { d.positions.map((pos, j) => {
if(pos < s.yUnitMinimums[j]) { if(pos < s.yExtremes[j]) {
s.yUnitMinimums[j] = pos; s.yExtremes[j] = pos;
} }
}); });
}); });
@ -212,7 +227,19 @@ export default class AxisChart extends BaseChart {
getAllYValues() { getAllYValues() {
// TODO: yMarkers, regions, sums, every Y value ever // 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() { calcIntermedState() {
@ -324,31 +351,50 @@ export default class AxisChart extends BaseChart {
if(d.chartType === 'line') { if(d.chartType === 'line') {
dataUnitsComponents.push(this.getPathComponent(d, index)); dataUnitsComponents.push(this.getPathComponent(d, index));
} }
console.log(this.unitRenderers[d.chartType], d.chartType);
let renderer = this.unitRenderers[d.chartType];
dataUnitsComponents.push(this.getDataUnitComponent( dataUnitsComponents.push(this.getDataUnitComponent(
d, index, this.unitRenderers[d.chartType] index, renderer
)); ));
}); });
return dataUnitsComponents; return dataUnitsComponents;
} }
getDataUnitComponent(d, index, unitRenderer) { getDataUnitComponent(index, unitRenderer) {
return new ChartComponent({ return new ChartComponent({
layerClass: 'dataset-units dataset-' + index, layerClass: 'dataset-units dataset-' + index,
preMake: () => { },
make: () => { make: () => {
let d = this.state.datasets[index]; 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 d.positions.map((y, j) => {
return unitRenderer.draw( return unitRenderer.draw(
this.state.xAxisPositions[j], this.state.xAxisPositions[j],
y, y,
this.colors[index], this.colors[index],
j, j
index, ,
this.state.noOfDatasets 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) => { animate: (svgUnits) => {
// have been updated in axis render; // have been updated in axis render;
let newX = this.state.xAxisPositions; let newX = this.state.xAxisPositions;
@ -494,9 +540,13 @@ export default class AxisChart extends BaseChart {
totalWidth: this.width, totalWidth: this.width,
zeroLine: this.state.zeroLine, zeroLine: this.state.zeroLine,
unitWidth: this.state.unitWidth, unitWidth: this.state.unitWidth,
noOfDatasets: this.state.noOfDatasets,
}; };
meta = Object.assign(meta, this.rawChartArgs.options);
Object.keys(this.unitRenderers).map(key => { Object.keys(this.unitRenderers).map(key => {
meta.options = this[key + 'Options'];
this.unitRenderers[key].refreshMeta(meta); this.unitRenderers[key].refreshMeta(meta);
}); });
} }
@ -518,7 +568,7 @@ export default class AxisChart extends BaseChart {
mapTooltipXPosition(relX) { mapTooltipXPosition(relX) {
let s = this.state; let s = this.state;
if(!s.yUnitMinimums) return; if(!s.yExtremes) return;
let titles = s.xAxisLabels; let titles = s.xAxisLabels;
if(this.formatTooltipX && this.formatTooltipX(titles[0])) { 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]; // let delta = i === 0 ? s.unitWidth : xVal - s.xAxisPositions[i-1];
if(relX > xVal - s.unitWidth/2) { if(relX > xVal - s.unitWidth/2) {
let x = xVal + this.translateXLeft; 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) => { let values = s.datasets.map((set, j) => {
return { return {

View File

@ -236,6 +236,13 @@ export default class BaseChart {
); );
this.svgDefs = makeSVGDefs(this.svg); 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.drawArea = makeSVGGroup(
this.svg, this.svg,
this.type + '-chart', this.type + '-chart',

View File

@ -2,17 +2,23 @@ import { getBarHeightAndYAttr } from '../utils/draw-utils';
import { createSVG, makePath, makeGradient } from '../utils/draw'; import { createSVG, makePath, makeGradient } from '../utils/draw';
import { STD_EASING, UNIT_ANIM_DUR, MARKER_LINE_ANIM_DUR, PATH_ANIM_DUR } from '../utils/animate'; 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 { class AxisChartController {
constructor(meta) { constructor(meta) {
// TODO: make configurable passing args // TODO: make configurable passing args
this.refreshMeta(meta); this.meta = meta || {};
this.setupArgs(); this.setupArgs();
} }
setupArgs() {} setupArgs() {
this.consts = {};
}
setup() {}
refreshMeta(meta) { refreshMeta(meta) {
this.meta = meta || {}; this.meta = Object.assign((this.meta || {}), meta);
} }
draw() {} draw() {}
@ -24,15 +30,13 @@ export class AxisController extends AxisChartController {
super(meta); super(meta);
} }
setupArgs() {}
draw(x, y, color, index) { draw(x, y, color, index) {
return createSVG('circle', { return createSVG('circle', {
style: `fill: ${color}`, style: `fill: ${color}`,
'data-point-index': index, 'data-point-index': index,
cx: x, cx: x,
cy: y, cy: y,
r: this.args.radius r: this.consts.radius
}); });
} }
@ -48,39 +52,40 @@ export class BarChartController extends AxisChartController {
} }
setupArgs() { setupArgs() {
this.args = { this.consts = {
spaceRatio: 0.5, spaceRatio: 0.5,
minHeight: this.meta.totalHeight * MIN_BAR_PERCENT_HEIGHT
}; };
} }
draw(x, yTop, color, index, datasetIndex, noOfDatasets) { refreshMeta(meta) {
let totalWidth = this.meta.unitWidth - this.meta.unitWidth * this.args.spaceRatio; if(meta) {
let startX = x - totalWidth/2; super.refreshMeta(meta);
}
let m = this.meta;
this.consts.barsWidth = m.unitWidth - m.unitWidth * this.consts.spaceRatio;
// temp commented this.consts.width = this.consts.barsWidth / (m.options && m.options.stacked
// let width = totalWidth / noOfDatasets; ? m.options.stacked : m.noOfDatasets);
// let currentX = startX + width * datasetIndex; }
// temp draw(x, yTop, color, index, offset=0) {
let width = totalWidth; let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine);
let currentX = startX;
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
return createSVG('rect', { return createSVG('rect', {
className: `bar mini`, className: `bar mini`,
style: `fill: ${color}`, style: `fill: ${color}`,
'data-point-index': index, 'data-point-index': index,
x: currentX, x: x - this.consts.barsWidth/2,
y: y, y: y - offset,
width: width, width: this.consts.width,
height: height height: height || this.consts.minHeight
}); });
} }
animate(bar, x, yTop, index, noOfDatasets) { animate(bar, x, yTop, index, noOfDatasets) {
let start = x - this.meta.avgUnitWidth/4; let start = x - this.meta.unitWidth/4;
let width = (this.meta.avgUnitWidth/2)/noOfDatasets; let width = (this.meta.unitWidth/2)/noOfDatasets;
let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight); let [height, y] = getBarHeightAndYAttr(yTop, this.meta.zeroLine, this.meta.totalHeight);
x = start + (width * index); x = start + (width * index);
@ -96,8 +101,7 @@ export class LineChartController extends AxisChartController {
} }
setupArgs() { setupArgs() {
console.log(this); this.consts = {
this.args = {
radius: this.meta.dotSize || 4 radius: this.meta.dotSize || 4
}; };
} }
@ -108,7 +112,7 @@ export class LineChartController extends AxisChartController {
'data-point-index': index, 'data-point-index': index,
cx: x, cx: x,
cy: y, cy: y,
r: this.args.radius r: this.consts.radius
}); });
} }

View File

@ -4,12 +4,18 @@ export class ChartComponent {
constructor({ constructor({
layerClass = '', layerClass = '',
layerTransform = '', layerTransform = '',
preMake,
make, make,
postMake,
animate animate
}) { }) {
this.layerClass = layerClass; this.layerClass = layerClass;
this.layerTransform = layerTransform; this.layerTransform = layerTransform;
this.preMake = preMake;
this.make = make; this.make = make;
this.postMake = postMake;
this.animate = animate; this.animate = animate;
this.layer = undefined; this.layer = undefined;
@ -19,12 +25,15 @@ export class ChartComponent {
refresh(args) {} refresh(args) {}
render() { render() {
this.preMake && this.preMake();
this.store = this.make(); this.store = this.make();
this.layer.textContent = ''; this.layer.textContent = '';
this.store.forEach(element => { this.store.forEach(element => {
this.layer.appendChild(element); this.layer.appendChild(element);
}); });
this.postMake && this.postMake(this.store, this.layer);
} }
setupParent(parent) { setupParent(parent) {

View File

@ -1,2 +0,0 @@
import { getBarHeightAndYAttr } from '../utils/draw-utils';

View File

@ -1,8 +1,6 @@
import { fillArray } from './helpers'; import { fillArray } from './helpers';
const MIN_BAR_PERCENT_HEIGHT = 0.01; export function getBarHeightAndYAttr(yTop, zeroLine) {
export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
let height, y; let height, y;
if (yTop <= zeroLine) { if (yTop <= zeroLine) {
height = zeroLine - yTop; height = zeroLine - yTop;
@ -16,11 +14,6 @@ export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
} else { } else {
height = yTop - zeroLine; height = yTop - zeroLine;
y = zeroLine; y = zeroLine;
// In case of invisible bars
if(height === 0) {
height = totalHeight * MIN_BAR_PERCENT_HEIGHT;
}
} }
return [height, y]; return [height, y];

View File

@ -236,7 +236,6 @@ export class AxisChartRenderer {
if(!options.pos) options.pos = 'bottom'; if(!options.pos) options.pos = 'bottom';
if(!options.offset) options.offset = 0; if(!options.offset) options.offset = 0;
if(!options.mode) options.mode = this.xAxisMode; if(!options.mode) options.mode = this.xAxisMode;
console.log(this.xAxisMode);
if(!options.stroke) options.stroke = BASE_LINE_COLOR; if(!options.stroke) options.stroke = BASE_LINE_COLOR;
if(!options.className) options.className = ''; if(!options.className) options.className = '';