setup Pie chart component slices

This commit is contained in:
Prateeksha Singh 2018-03-05 20:51:31 +05:30
parent 21238c9c8e
commit ded80791dd
15 changed files with 597 additions and 522 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -47,10 +47,6 @@ export default class AggregationChart extends BaseChart {
}); });
} }
render() { }
bindTooltip() { }
renderLegend() { renderLegend() {
let s = this.state; let s = this.state;

View File

@ -215,8 +215,6 @@ export default class AxisChart extends BaseChart {
let barDatasets = this.state.datasets.filter(d => d.chartType === 'bar'); let barDatasets = this.state.datasets.filter(d => d.chartType === 'bar');
let lineDatasets = this.state.datasets.filter(d => d.chartType === 'line'); let lineDatasets = this.state.datasets.filter(d => d.chartType === 'line');
// console.log('barDatasets', barDatasets, this.state.datasets);
let barsConfigs = barDatasets.map(d => { let barsConfigs = barDatasets.map(d => {
let index = d.index; let index = d.index;
return [ return [
@ -480,12 +478,10 @@ export default class AxisChart extends BaseChart {
addDataPoint(label, datasetValues, index=this.state.datasetLength) { addDataPoint(label, datasetValues, index=this.state.datasetLength) {
super.addDataPoint(label, datasetValues, index); super.addDataPoint(label, datasetValues, index);
// console.log(label, datasetValues, this.data.labels);
this.data.labels.splice(index, 0, label); this.data.labels.splice(index, 0, label);
this.data.datasets.map((d, i) => { this.data.datasets.map((d, i) => {
d.values.splice(index, 0, datasetValues[i]); d.values.splice(index, 0, datasetValues[i]);
}); });
// console.log(this.data);
this.update(this.data); this.update(this.data);
} }
@ -498,9 +494,6 @@ export default class AxisChart extends BaseChart {
this.update(this.data); this.update(this.data);
} }
// getDataPoint(index = 0) {}
// setCurrentDataPoint(point) {}
updateDataset(datasetValues, index=0) { updateDataset(datasetValues, index=0) {
this.data.datasets[index].values = datasetValues; this.data.datasets[index].values = datasetValues;
this.update(this.data); this.update(this.data);
@ -514,7 +507,3 @@ export default class AxisChart extends BaseChart {
// addDataPoint(dataPoint, index = 0) {} // addDataPoint(dataPoint, index = 0) {}
// removeDataPoint(index = 0) {} // removeDataPoint(index = 0) {}
} }
// keep a binding at the end of chart

View File

@ -34,6 +34,8 @@ export default class BaseChart {
this.state = {}; this.state = {};
this.options = {}; this.options = {};
this.initTimeout = INIT_CHART_UPDATE_TIMEOUT;
if(this.config.isNavigable) { if(this.config.isNavigable) {
this.overlays = []; this.overlays = [];
} }
@ -138,7 +140,7 @@ export default class BaseChart {
if(init) { if(init) {
this.data = this.realData; this.data = this.realData;
setTimeout(() => {this.update();}, INIT_CHART_UPDATE_TIMEOUT); setTimeout(() => {this.update();}, this.initTimeout);
} }
this.renderLegend(); this.renderLegend();

View File

@ -35,8 +35,8 @@ export default class PercentageChart extends AggregationChart {
render() { render() {
let s = this.state; let s = this.state;
this.grand_total = s.sliceTotals.reduce((a, b) => a + b, 0); this.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
this.slices = []; s.slices = [];
s.sliceTotals.map((total, i) => { s.sliceTotals.map((total, i) => {
let slice = $.create('div', { let slice = $.create('div', {
className: `progress-bar`, className: `progress-bar`,
@ -44,10 +44,10 @@ export default class PercentageChart extends AggregationChart {
inside: this.percentageBar, inside: this.percentageBar,
styles: { styles: {
background: this.colors[i], background: this.colors[i],
width: total*100/this.grand_total + "%" width: total*100/this.grandTotal + "%"
} }
}); });
this.slices.push(slice); s.slices.push(slice);
}); });
} }
@ -59,13 +59,13 @@ export default class PercentageChart extends AggregationChart {
if(slice.classList.contains('progress-bar')) { if(slice.classList.contains('progress-bar')) {
let i = slice.getAttribute('data-index'); let i = slice.getAttribute('data-index');
let g_off = getOffset(this.chartWrapper), p_off = getOffset(slice); let gOff = getOffset(this.chartWrapper), pOff = getOffset(slice);
let x = p_off.left - g_off.left + slice.offsetWidth/2; let x = pOff.left - gOff.left + slice.offsetWidth/2;
let y = p_off.top - g_off.top - 6; let y = pOff.top - gOff.top - 6;
let title = (this.formatted_labels && this.formatted_labels.length>0 let title = (this.formattedLabels && this.formattedLabels.length>0
? this.formatted_labels[i] : this.state.labels[i]) + ': '; ? this.formattedLabels[i] : this.state.labels[i]) + ': ';
let percent = (s.sliceTotals[i]*100/this.grand_total).toFixed(1); let percent = (s.sliceTotals[i]*100/this.grandTotal).toFixed(1);
this.tip.setValues(x, y, title, percent + "%"); this.tip.setValues(x, y, title, percent + "%");
this.tip.showTip(); this.tip.showTip();

View File

@ -1,5 +1,6 @@
import AggregationChart from './AggregationChart'; import AggregationChart from './AggregationChart';
import { $, getOffset } from '../utils/dom'; import { getComponent } from '../objects/ChartComponents';
import { getOffset } from '../utils/dom';
import { getPositionByAngle } from '../utils/helpers'; import { getPositionByAngle } from '../utils/helpers';
import { makePath, makeArcPathStr } from '../utils/draw'; import { makePath, makeArcPathStr } from '../utils/draw';
import { lightenDarkenColor } from '../utils/colors'; import { lightenDarkenColor } from '../utils/colors';
@ -10,10 +11,7 @@ export default class PieChart extends AggregationChart {
constructor(parent, args) { constructor(parent, args) {
super(parent, args); super(parent, args);
this.type = 'pie'; this.type = 'pie';
this.initTimeout = 0;
this.hoverRadio = args.hoverRadio || 0.1;
this.startAngle = args.startAngle || 0;
this.clockWise = args.clockWise || false;
this.setup(); this.setup();
} }
@ -22,68 +20,98 @@ export default class PieChart extends AggregationChart {
super.configure(args); super.configure(args);
this.mouseMove = this.mouseMove.bind(this); this.mouseMove = this.mouseMove.bind(this);
this.mouseLeave = this.mouseLeave.bind(this); this.mouseLeave = this.mouseLeave.bind(this);
this.hoverRadio = args.hoverRadio || 0.1;
this.config.startAngle = args.startAngle || 0;
this.clockWise = args.clockWise || false;
} }
prepareFirstData(data=this.data) {
this.init = 1;
return data;
}
calc() { calc() {
super.calc(); super.calc();
let s = this.state;
this.center = { this.center = {
x: this.width / 2, x: this.width / 2,
y: this.height / 2 y: this.height / 2
} }
this.radius = (this.height > this.width ? this.center.x : this.center.y); this.radius = (this.height > this.width ? this.center.x : this.center.y);
s.grandTotal = s.sliceTotals.reduce((a, b) => a + b, 0);
this.calcSlices();
} }
render(init) { calcSlices() {
const{radius,clockWise} = this; let s = this.state;
this.grand_total = this.state.sliceTotals.reduce((a, b) => a + b, 0); const { radius, clockWise } = this;
const prevSlicesProperties = this.slicesProperties || [];
this.slices = [];
this.elements_to_animate = [];
this.slicesProperties = [];
let curAngle = 180 - this.startAngle;
this.state.sliceTotals.map((total, i) => { const prevSlicesProperties = s.slicesProperties || [];
s.sliceStrings = [];
s.slicesProperties = [];
let curAngle = 180 - this.config.startAngle;
s.sliceTotals.map((total, i) => {
const startAngle = curAngle; const startAngle = curAngle;
const originDiffAngle = (total / this.grand_total) * FULL_ANGLE; const originDiffAngle = (total / s.grandTotal) * FULL_ANGLE;
const diffAngle = clockWise ? -originDiffAngle : originDiffAngle; const diffAngle = clockWise ? -originDiffAngle : originDiffAngle;
const endAngle = curAngle = curAngle + diffAngle; const endAngle = curAngle = curAngle + diffAngle;
const startPosition = getPositionByAngle(startAngle, radius); const startPosition = getPositionByAngle(startAngle, radius);
const endPosition = getPositionByAngle(endAngle, radius); const endPosition = getPositionByAngle(endAngle, radius);
const prevProperty = init && prevSlicesProperties[i];
const prevProperty = this.init && prevSlicesProperties[i];
let curStart,curEnd; let curStart,curEnd;
if(init){ if(this.init) {
curStart = prevProperty?prevProperty.startPosition : startPosition; curStart = prevProperty ? prevProperty.startPosition : startPosition;
curEnd = prevProperty? prevProperty.endPosition : startPosition; curEnd = prevProperty ? prevProperty.endPosition : startPosition;
}else{ } else {
curStart = startPosition; curStart = startPosition;
curEnd = endPosition; curEnd = endPosition;
} }
const curPath = makeArcPathStr(curStart, curEnd, this.center, this.radius, this.clockWise); const curPath = makeArcPathStr(curStart, curEnd, this.center, this.radius, this.clockWise);
let slice = makePath(curPath, 'pie-path', 'none', this.colors[i]);
slice.style.transition = 'transform .3s;';
this.drawArea.appendChild(slice);
this.slices.push(slice); s.sliceStrings.push(curPath);
this.slicesProperties.push({ s.slicesProperties.push({
startPosition, startPosition,
endPosition, endPosition,
value: total, value: total,
total: this.grand_total, total: s.grandTotal,
startAngle, startAngle,
endAngle, endAngle,
angle: diffAngle angle: diffAngle
}); });
if(init){
this.elements_to_animate.push([slice,
{d: makeArcPathStr(startPosition, endPosition, this.center, this.radius, this.clockWise)},
650, "easein",null,{
d:curPath
}]);
}
}); });
// if(init){ this.init = 0;
// runSMILAnimation(this.chartWrapper, this.svg, this.elements_to_animate); }
// }
setupComponents() {
let s = this.state;
let componentConfigs = [
[
'pieSlices',
{ },
function() {
return {
sliceStrings: s.sliceStrings,
colors: this.colors
}
}.bind(this)
]
];
this.components = new Map(componentConfigs
.map(args => {
let component = getComponent(...args);
return [args[0], component];
}));
} }
calTranslateByAngle(property){ calTranslateByAngle(property){
@ -96,43 +124,45 @@ export default class PieChart extends AggregationChart {
if(!path) return; if(!path) return;
const color = this.colors[i]; const color = this.colors[i];
if(flag) { if(flag) {
transform(path, this.calTranslateByAngle(this.state.slicesProperties[i]));
transform(path, this.calTranslateByAngle(this.slicesProperties[i]));
path.style.fill = lightenDarkenColor(color, 50); path.style.fill = lightenDarkenColor(color, 50);
let g_off = getOffset(this.svg); let g_off = getOffset(this.svg);
let x = e.pageX - g_off.left + 10; let x = e.pageX - g_off.left + 10;
let y = e.pageY - g_off.top - 10; let y = e.pageY - g_off.top - 10;
let title = (this.formatted_labels && this.formatted_labels.length > 0 let title = (this.formatted_labels && this.formatted_labels.length > 0
? this.formatted_labels[i] : this.state.labels[i]) + ': '; ? this.formatted_labels[i] : this.state.labels[i]) + ': ';
let percent = (this.state.sliceTotals[i]*100/this.grand_total).toFixed(1); let percent = (this.state.sliceTotals[i] * 100 / this.state.grandTotal).toFixed(1);
this.tip.set_values(x, y, title, percent + "%"); this.tip.setValues(x, y, title, percent + "%");
this.tip.show_tip(); this.tip.showTip();
} else { } else {
transform(path,'translate3d(0,0,0)'); transform(path,'translate3d(0,0,0)');
this.tip.hide_tip(); this.tip.hideTip();
path.style.fill = color; path.style.fill = color;
} }
} }
bindTooltip() {
this.chartWrapper.addEventListener('mousemove', this.mouseMove);
this.chartWrapper.addEventListener('mouseleave', this.mouseLeave);
}
mouseMove(e){ mouseMove(e){
const target = e.target; const target = e.target;
let slices = this.components.get('pieSlices').store;
let prevIndex = this.curActiveSliceIndex; let prevIndex = this.curActiveSliceIndex;
let prevAcitve = this.curActiveSlice; let prevAcitve = this.curActiveSlice;
for(let i = 0; i < this.slices.length; i++){ if(slices.includes(target)) {
if(target === this.slices[i]){ let i = slices.indexOf(target);
this.hoverSlice(prevAcitve,prevIndex,false); this.hoverSlice(prevAcitve, prevIndex,false);
this.curActiveSlice = target; this.curActiveSlice = target;
this.curActiveSliceIndex = i; this.curActiveSliceIndex = i;
this.hoverSlice(target,i,true,e); this.hoverSlice(target, i, true, e);
break; } else {
} this.mouseLeave();
} }
} }
mouseLeave(){ mouseLeave(){
this.hoverSlice(this.curActiveSlice,this.curActiveSliceIndex,false); this.hoverSlice(this.curActiveSlice,this.curActiveSliceIndex,false);
} }
bindTooltip() {
// this.drawArea.addEventListener('mousemove',this.mouseMove);
// this.drawArea.addEventListener('mouseleave',this.mouseLeave);
}
} }

View File

@ -1,7 +1,8 @@
import { makeSVGGroup } from '../utils/draw'; import { makeSVGGroup } from '../utils/draw';
import { xLine, yLine, yMarker, yRegion, datasetBar, datasetDot, getPaths } from '../utils/draw'; import { makePath, xLine, yLine, yMarker, yRegion, datasetBar, datasetDot, getPaths } from '../utils/draw';
import { equilizeNoOfElements } from '../utils/draw-utils'; import { equilizeNoOfElements } from '../utils/draw-utils';
import { translateHoriLine, translateVertLine, animateRegion, animateBar, animateDot, animatePath } from '../utils/animate'; import { translateHoriLine, translateVertLine, animateRegion, animateBar,
animateDot, animatePath, animatePathStr } from '../utils/animate';
class ChartComponent { class ChartComponent {
constructor({ constructor({
@ -63,6 +64,22 @@ class ChartComponent {
} }
let componentConfigs = { let componentConfigs = {
pieSlices: {
layerClass: 'pie-slices',
makeElements(data) {
return data.sliceStrings.map((s, i) =>{
let slice = makePath(s, 'pie-path', 'none', data.colors[i]);
slice.style.transition = 'transform .3s;';
return slice;
});
},
animateElements(newData) {
return this.store.map((slice, i) =>
animatePathStr(slice, newData.sliceStrings[i])
);
}
},
yAxis: { yAxis: {
layerClass: 'y axis', layerClass: 'y axis',
makeElements(data) { makeElements(data) {

View File

@ -99,3 +99,7 @@ export function animatePath(paths, newXList, newYList, zeroLine) {
return pathComponents; return pathComponents;
} }
export function animatePathStr(oldPath, pathStr) {
return [oldPath, {d: pathStr}, UNIT_ANIM_DUR, STD_EASING];
}

View File

@ -14,13 +14,13 @@ export function getBarHeightAndYAttr(yTop, zeroLine) {
} }
export function equilizeNoOfElements(array1, array2, export function equilizeNoOfElements(array1, array2,
extra_count=array2.length - array1.length) { extraCount = array2.length - array1.length) {
// Doesn't work if either has zero elements. // Doesn't work if either has zero elements.
if(extra_count > 0) { if(extraCount > 0) {
array1 = fillArray(array1, extra_count); array1 = fillArray(array1, extraCount);
} else { } else {
array2 = fillArray(array2, extra_count); array2 = fillArray(array2, extraCount);
} }
return [array1, array2]; return [array1, array2];
} }