@@ -234,7 +234,7 @@ function getStringWidth(string, charWidth) { | |||||
function getBarHeightAndYAttr(yTop, zeroLine) { | function getBarHeightAndYAttr(yTop, zeroLine) { | ||||
let height, y; | let height, y; | ||||
if (yTop < zeroLine) { | |||||
if (yTop <= zeroLine) { | |||||
height = zeroLine - yTop; | height = zeroLine - yTop; | ||||
y = yTop; | y = yTop; | ||||
} else { | } else { | ||||
@@ -286,13 +286,14 @@ const REPLACE_ALL_NEW_DUR = 250; | |||||
const STD_EASING = 'easein'; | const STD_EASING = 'easein'; | ||||
function translate(unit, oldCoord, newCoord, duration) { | function translate(unit, oldCoord, newCoord, duration) { | ||||
let old = typeof oldCoord === 'string' ? oldCoord : oldCoord.join(', '); | |||||
return [ | return [ | ||||
unit, | unit, | ||||
{transform: newCoord.join(', ')}, | {transform: newCoord.join(', ')}, | ||||
duration, | duration, | ||||
STD_EASING, | STD_EASING, | ||||
"translate", | "translate", | ||||
{transform: oldCoord.join(', ')} | |||||
{transform: old} | |||||
]; | ]; | ||||
} | } | ||||
@@ -319,6 +320,42 @@ function animateRegion(rectGroup, newY1, newY2, oldY2) { | |||||
return [rectAnim, groupAnim]; | return [rectAnim, groupAnim]; | ||||
} | } | ||||
function animateBar(bar, x, yTop, width, index=0, meta={}) { | |||||
let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine); | |||||
if(bar.nodeName !== 'rect') { | |||||
let rect = bar.childNodes[0]; | |||||
let rectAnim = [ | |||||
rect, | |||||
{width: width, height: height}, | |||||
UNIT_ANIM_DUR, | |||||
STD_EASING | |||||
]; | |||||
let old = bar.getAttribute("transform").split("(")[1].slice(0, -1); | |||||
let groupAnim = translate(bar, old, [x, y], MARKER_LINE_ANIM_DUR); | |||||
return [rectAnim, groupAnim]; | |||||
} else { | |||||
return [[bar, {width: width, height: height, x: x, y: y}, UNIT_ANIM_DUR, STD_EASING]]; | |||||
} | |||||
// bar.animate({height: args.newHeight, y: yTop}, UNIT_ANIM_DUR, mina.easein); | |||||
} | |||||
/* | |||||
<filter id="glow" x="-10%" y="-10%" width="120%" height="120%"> | |||||
<feGaussianBlur stdDeviation="0.5 0.5" result="glow"></feGaussianBlur> | |||||
<feMerge> | |||||
<feMergeNode in="glow"></feMergeNode> | |||||
<feMergeNode in="glow"></feMergeNode> | |||||
<feMergeNode in="glow"></feMergeNode> | |||||
</feMerge> | |||||
</filter> | |||||
filter: url(#glow); | |||||
fill: #fff; | |||||
*/ | |||||
const AXIS_TICK_LENGTH = 6; | const AXIS_TICK_LENGTH = 6; | ||||
const LABEL_MARGIN = 4; | const LABEL_MARGIN = 4; | ||||
const FONT_SIZE = 10; | const FONT_SIZE = 10; | ||||
@@ -383,13 +420,7 @@ 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') { | function makePath(pathStr, className='', stroke='none', fill='none') { | ||||
return createSVG('path', { | return createSVG('path', { | ||||
@@ -627,31 +658,40 @@ function yRegion(y1, y2, width, label) { | |||||
function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={}) { | function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={}) { | ||||
let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine); | let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine); | ||||
// console.log(yTop, meta.zeroLine, y, offset); | // console.log(yTop, meta.zeroLine, y, offset); | ||||
y -= offset; | |||||
let rect = createSVG('rect', { | let rect = createSVG('rect', { | ||||
className: `bar mini`, | className: `bar mini`, | ||||
style: `fill: ${color}`, | style: `fill: ${color}`, | ||||
'data-point-index': index, | 'data-point-index': index, | ||||
x: x - meta.barsWidth/2, | |||||
y: y - offset, | |||||
x: x, | |||||
y: y, | |||||
width: width, | width: width, | ||||
height: height || meta.minHeight | |||||
height: height || meta.minHeight // TODO: correct y for positive min height | |||||
}); | }); | ||||
if(!label && !label.length) { | if(!label && !label.length) { | ||||
return rect; | return rect; | ||||
} else { | } else { | ||||
rect.setAttribute('y', 0); | |||||
rect.setAttribute('x', 0); | |||||
let text = createSVG('text', { | let text = createSVG('text', { | ||||
className: 'data-point-value', | className: 'data-point-value', | ||||
x: x, | |||||
y: y - offset, | |||||
x: width/2, | |||||
y: 0, | |||||
dy: (FONT_SIZE / 2 * -1) + 'px', | dy: (FONT_SIZE / 2 * -1) + 'px', | ||||
'font-size': FONT_SIZE + 'px', | 'font-size': FONT_SIZE + 'px', | ||||
'text-anchor': 'middle', | 'text-anchor': 'middle', | ||||
innerHTML: label | innerHTML: label | ||||
}); | }); | ||||
return wrapInSVGGroup([rect, text]); | |||||
let group = createSVG('g', { | |||||
transform: `translate(${x}, ${y})` | |||||
}); | |||||
group.appendChild(rect); | |||||
group.appendChild(text); | |||||
return group; | |||||
} | } | ||||
} | } | ||||
@@ -1227,11 +1267,11 @@ function zeroDataPrep(realData) { | |||||
let zeroArray = new Array(datasetLength).fill(0); | let zeroArray = new Array(datasetLength).fill(0); | ||||
let zeroData = { | let zeroData = { | ||||
labels: realData.labels, | |||||
labels: realData.labels.slice(0, -1), | |||||
datasets: realData.datasets.map(d => { | datasets: realData.datasets.map(d => { | ||||
return { | return { | ||||
name: '', | name: '', | ||||
values: zeroArray, | |||||
values: zeroArray.slice(0, -1), | |||||
chartType: d.chartType | chartType: d.chartType | ||||
} | } | ||||
}), | }), | ||||
@@ -1261,14 +1301,12 @@ class ChartComponent$1 { | |||||
getData, | getData, | ||||
makeElements, | makeElements, | ||||
postMake, | |||||
animateElements | animateElements | ||||
}) { | }) { | ||||
this.layerTransform = layerTransform; | this.layerTransform = layerTransform; | ||||
this.constants = constants; | this.constants = constants; | ||||
this.makeElements = makeElements; | this.makeElements = makeElements; | ||||
this.postMake = postMake; | |||||
this.getData = getData; | this.getData = getData; | ||||
this.animateElements = animateElements; | this.animateElements = animateElements; | ||||
@@ -1291,9 +1329,7 @@ class ChartComponent$1 { | |||||
} | } | ||||
make() { | make() { | ||||
this.preMake && this.preMake(); | |||||
this.render(this.data); | this.render(this.data); | ||||
this.postMake && this.postMake(); | |||||
this.oldData = this.data; | this.oldData = this.data; | ||||
} | } | ||||
@@ -1331,8 +1367,8 @@ let componentConfigs = { | |||||
}, | }, | ||||
animateElements(newData) { | animateElements(newData) { | ||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let oldPos = this.oldData.positions; | let oldPos = this.oldData.positions; | ||||
let oldLabels = this.oldData.labels; | let oldLabels = this.oldData.labels; | ||||
@@ -1362,8 +1398,8 @@ let componentConfigs = { | |||||
}, | }, | ||||
animateElements(newData) { | animateElements(newData) { | ||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let oldPos = this.oldData.positions; | let oldPos = this.oldData.positions; | ||||
let oldLabels = this.oldData.labels; | let oldLabels = this.oldData.labels; | ||||
@@ -1394,8 +1430,8 @@ let componentConfigs = { | |||||
animateElements(newData) { | animateElements(newData) { | ||||
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | [this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | ||||
let newPos = newData.map(d => d.position); | |||||
let newLabels = newData.map(d => d.label); | |||||
let newPos = newData.map(d => d.position); | |||||
let newLabels = newData.map(d => d.label); | |||||
let oldPos = this.oldData.map(d => d.position); | let oldPos = this.oldData.map(d => d.position); | ||||
let oldLabels = this.oldData.map(d => d.label); | let oldLabels = this.oldData.map(d => d.label); | ||||
@@ -1426,9 +1462,9 @@ let componentConfigs = { | |||||
animateElements(newData) { | 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 oldPos = this.oldData.map(d => d.end); | ||||
let oldLabels = this.oldData.map(d => d.label); | let oldLabels = this.oldData.map(d => d.label); | ||||
@@ -1459,57 +1495,67 @@ let componentConfigs = { | |||||
makeElements(data) { | makeElements(data) { | ||||
let c = this.constants; | let c = this.constants; | ||||
return data.yPositions.map((y, j) => { | return data.yPositions.map((y, j) => { | ||||
// console.log(data.cumulativeYPos, data.cumulativeYPos[j]); | |||||
return datasetBar( | return datasetBar( | ||||
data.xPositions[j], | data.xPositions[j], | ||||
y, | y, | ||||
c.barWidth, | |||||
data.barWidth, | |||||
c.color, | c.color, | ||||
(c.valuesOverPoints ? (c.stacked ? data.cumulativeYs[j] : data.values[j]) : ''), | (c.valuesOverPoints ? (c.stacked ? data.cumulativeYs[j] : data.values[j]) : ''), | ||||
j, | j, | ||||
y - (c.stacked ? data.cumulativeYPos[j] : y), | y - (c.stacked ? data.cumulativeYPos[j] : y), | ||||
{ | { | ||||
zeroLine: c.zeroLine, | |||||
barsWidth: c.barsWidth, | |||||
zeroLine: data.zeroLine, | |||||
barsWidth: data.barsWidth, | |||||
minHeight: c.minHeight | minHeight: c.minHeight | ||||
} | } | ||||
) | ) | ||||
}); | }); | ||||
}, | }, | ||||
postMake() { | |||||
if((!this.constants.stacked)) { | |||||
this.layer.setAttribute('transform', | |||||
`translate(${this.constants.width * this.constants.index}, 0)`); | |||||
} | |||||
}, | |||||
animateElements(newData) { | animateElements(newData) { | ||||
// [this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | |||||
let c = this.constants; | |||||
let newXPos = newData.xPositions; | |||||
let newYPos = newData.yPositions; | |||||
let newCYPos = newData.cumulativeYPos; | |||||
let newValues = newData.values; | |||||
let newCYs = newData.cumulativeYs; | |||||
// let newPos = newData.map(d => d.end); | |||||
// let newLabels = newData.map(d => d.label); | |||||
// let newStarts = newData.map(d => d.start); | |||||
let oldXPos = this.oldData.xPositions; | |||||
let oldYPos = this.oldData.yPositions; | |||||
let oldCYPos = this.oldData.cumulativeYPos; | |||||
let oldValues = this.oldData.values; | |||||
let oldCYs = this.oldData.cumulativeYs; | |||||
// let oldPos = this.oldData.map(d => d.end); | |||||
// let oldLabels = this.oldData.map(d => d.label); | |||||
// let oldStarts = this.oldData.map(d => d.start); | |||||
[oldXPos, newXPos] = equilizeNoOfElements(oldXPos, newXPos); | |||||
[oldYPos, newYPos] = equilizeNoOfElements(oldYPos, newYPos); | |||||
[oldCYPos, newCYPos] = equilizeNoOfElements(oldCYPos, newCYPos); | |||||
[oldValues, newValues] = equilizeNoOfElements(oldValues, newValues); | |||||
[oldCYs, newCYs] = equilizeNoOfElements(oldCYs, newCYs); | |||||
// this.render(oldPos.map((pos, i) => { | |||||
// return { | |||||
// start: oldStarts[i], | |||||
// end: oldPos[i], | |||||
// label: newLabels[i] | |||||
// } | |||||
// })); | |||||
this.render({ | |||||
xPositions: oldXPos, | |||||
yPositions: oldYPos, | |||||
cumulativeYPos: oldCYPos, | |||||
values: newValues, | |||||
cumulativeYs: newCYs, | |||||
zeroLine: this.oldData.zeroLine, | |||||
barsWidth: this.oldData.barsWidth, | |||||
barWidth: this.oldData.barWidth, | |||||
}); | |||||
// let animateElements = []; | |||||
let animateElements = []; | |||||
// this.store.map((rectGroup, i) => { | |||||
// animateElements = animateElements.concat(animateRegion( | |||||
// rectGroup, newStarts[i], newPos[i], oldPos[i] | |||||
// )); | |||||
// }); | |||||
this.store.map((bar, i) => { | |||||
animateElements = animateElements.concat(animateBar( | |||||
bar, newXPos[i], newYPos[i], newData.barWidth, c.index, | |||||
{zeroLine: newData.zeroLine} | |||||
)); | |||||
}); | |||||
// return animateElements; | |||||
return animateElements; | |||||
} | } | ||||
}, | }, | ||||
@@ -1519,7 +1565,8 @@ let componentConfigs = { | |||||
}; | }; | ||||
function getComponent(name, constants, getData) { | function getComponent(name, constants, getData) { | ||||
let config = componentConfigs[name]; | |||||
let keys = Object.keys(componentConfigs).filter(k => name.includes(k)); | |||||
let config = componentConfigs[keys[0]]; | |||||
Object.assign(config, { | Object.assign(config, { | ||||
constants: constants, | constants: constants, | ||||
getData: getData | getData: getData | ||||
@@ -1891,9 +1938,6 @@ class AxisChart extends BaseChart { | |||||
} | } | ||||
initComponents() { | initComponents() { | ||||
let s = this.state; | |||||
// console.log('this.state', Object.assign({}, this.state)); | |||||
// console.log('this.state', this.state); | |||||
this.componentConfigs = [ | this.componentConfigs = [ | ||||
[ | [ | ||||
'yAxis', | 'yAxis', | ||||
@@ -1936,14 +1980,11 @@ class AxisChart extends BaseChart { | |||||
// console.log('barDatasets', barDatasets, this.state.datasets); | // console.log('barDatasets', barDatasets, this.state.datasets); | ||||
// Bars | // 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 barsConfigs = barDatasets.map(d => { | ||||
let index = d.index; | let index = d.index; | ||||
return [ | return [ | ||||
'barGraph', | |||||
'barGraph' + '-' + d.index, | |||||
{ | { | ||||
index: index, | index: index, | ||||
color: this.colors[index], | color: this.colors[index], | ||||
@@ -1951,20 +1992,28 @@ class AxisChart extends BaseChart { | |||||
// same for all datasets | // same for all datasets | ||||
valuesOverPoints: this.valuesOverPoints, | valuesOverPoints: this.valuesOverPoints, | ||||
minHeight: this.height * MIN_BAR_PERCENT_HEIGHT, | minHeight: this.height * MIN_BAR_PERCENT_HEIGHT, | ||||
barsWidth: barsWidth, | |||||
barWidth: barWidth, | |||||
zeroLine: s.yAxis.zeroLine | |||||
}, | }, | ||||
function() { | function() { | ||||
let s = this.state; | let s = this.state; | ||||
let d = s.datasets[index]; | let d = s.datasets[index]; | ||||
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 xPositions = s.xAxis.positions.map(x => x - barsWidth/2 + barWidth * index); | |||||
return { | return { | ||||
xPositions: s.xAxis.positions, | |||||
xPositions: xPositions, | |||||
yPositions: d.yPositions, | yPositions: d.yPositions, | ||||
cumulativeYPos: d.cumulativeYPos, | cumulativeYPos: d.cumulativeYPos, | ||||
values: d.values, | values: d.values, | ||||
cumulativeYs: d.cumulativeYs | |||||
cumulativeYs: d.cumulativeYs, | |||||
zeroLine: s.yAxis.zeroLine, | |||||
barsWidth: barsWidth, | |||||
barWidth: barWidth, | |||||
}; | }; | ||||
}.bind(this) | }.bind(this) | ||||
]; | ]; | ||||
@@ -1,7 +1,7 @@ | |||||
// Composite Chart | // Composite Chart | ||||
// ================================================================================ | // ================================================================================ | ||||
let report_count_list = [17, 40, 33, 44, 126, 156, | let report_count_list = [17, 40, 33, 44, 126, 156, | ||||
324, 333, 478, 495, 373]; | |||||
324, 333, 478, 495, 176]; | |||||
let bar_composite_data = { | let bar_composite_data = { | ||||
labels: ["2007", "2008", "2009", "2010", "2011", "2012", | labels: ["2007", "2008", "2009", "2010", "2011", "2012", | ||||
@@ -209,14 +209,11 @@ export default class AxisChart extends BaseChart { | |||||
// console.log('barDatasets', barDatasets, this.state.datasets); | // console.log('barDatasets', barDatasets, this.state.datasets); | ||||
// Bars | // 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 barsConfigs = barDatasets.map(d => { | ||||
let index = d.index; | let index = d.index; | ||||
return [ | return [ | ||||
'barGraph', | |||||
'barGraph' + '-' + d.index, | |||||
{ | { | ||||
index: index, | index: index, | ||||
color: this.colors[index], | color: this.colors[index], | ||||
@@ -224,20 +221,28 @@ export default class AxisChart extends BaseChart { | |||||
// same for all datasets | // same for all datasets | ||||
valuesOverPoints: this.valuesOverPoints, | valuesOverPoints: this.valuesOverPoints, | ||||
minHeight: this.height * MIN_BAR_PERCENT_HEIGHT, | minHeight: this.height * MIN_BAR_PERCENT_HEIGHT, | ||||
barsWidth: barsWidth, | |||||
barWidth: barWidth, | |||||
zeroLine: s.yAxis.zeroLine | |||||
}, | }, | ||||
function() { | function() { | ||||
let s = this.state; | let s = this.state; | ||||
let d = s.datasets[index]; | let d = s.datasets[index]; | ||||
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 xPositions = s.xAxis.positions.map(x => x - barsWidth/2 + barWidth * index); | |||||
return { | return { | ||||
xPositions: s.xAxis.positions, | |||||
xPositions: xPositions, | |||||
yPositions: d.yPositions, | yPositions: d.yPositions, | ||||
cumulativeYPos: d.cumulativeYPos, | cumulativeYPos: d.cumulativeYPos, | ||||
values: d.values, | values: d.values, | ||||
cumulativeYs: d.cumulativeYs | |||||
cumulativeYs: d.cumulativeYs, | |||||
zeroLine: s.yAxis.zeroLine, | |||||
barsWidth: barsWidth, | |||||
barWidth: barWidth, | |||||
}; | }; | ||||
}.bind(this) | }.bind(this) | ||||
]; | ]; | ||||
@@ -64,11 +64,11 @@ export function zeroDataPrep(realData) { | |||||
let zeroArray = new Array(datasetLength).fill(0); | let zeroArray = new Array(datasetLength).fill(0); | ||||
let zeroData = { | let zeroData = { | ||||
labels: realData.labels, | |||||
labels: realData.labels.slice(0, -1), | |||||
datasets: realData.datasets.map(d => { | datasets: realData.datasets.map(d => { | ||||
return { | return { | ||||
name: '', | name: '', | ||||
values: zeroArray, | |||||
values: zeroArray.slice(0, -1), | |||||
chartType: d.chartType | chartType: d.chartType | ||||
} | } | ||||
}), | }), | ||||
@@ -44,41 +44,6 @@ export class AxisController extends AxisChartController { | |||||
} | } | ||||
} | } | ||||
export class BarChartController extends AxisChartController { | |||||
constructor(meta) { | |||||
super(meta); | |||||
} | |||||
setupArgs() { | |||||
this.consts = { | |||||
spaceRatio: 0.5, | |||||
minHeight: this.meta.totalHeight * MIN_BAR_PERCENT_HEIGHT | |||||
}; | |||||
} | |||||
refreshMeta(meta) { | |||||
if(meta) { | |||||
super.refreshMeta(meta); | |||||
} | |||||
let m = this.meta; | |||||
this.consts.barsWidth = m.unitWidth - m.unitWidth * this.consts.spaceRatio; | |||||
this.consts.width = this.consts.barsWidth / (m.options && m.options.stacked | |||||
? m.options.stacked : m.noOfDatasets); | |||||
} | |||||
animate(bar, x, yTop, index, 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); | |||||
return [bar, {width: width, height: height, x: x, y: y}, UNIT_ANIM_DUR, STD_EASING]; | |||||
// bar.animate({height: args.newHeight, y: yTop}, UNIT_ANIM_DUR, mina.easein); | |||||
} | |||||
} | |||||
export class LineChartController extends AxisChartController { | export class LineChartController extends AxisChartController { | ||||
constructor(meta) { | constructor(meta) { | ||||
super(meta); | super(meta); | ||||
@@ -1,7 +1,7 @@ | |||||
import { makeSVGGroup } from '../utils/draw'; | import { makeSVGGroup } from '../utils/draw'; | ||||
import { xLine, yLine, yMarker, yRegion, datasetBar } from '../utils/draw'; | import { xLine, yLine, yMarker, yRegion, datasetBar } from '../utils/draw'; | ||||
import { equilizeNoOfElements } from '../utils/draw-utils'; | import { equilizeNoOfElements } from '../utils/draw-utils'; | ||||
import { Animator, translateHoriLine, translateVertLine, animateRegion } from '../utils/animate'; | |||||
import { Animator, translateHoriLine, translateVertLine, animateRegion, animateBar } from '../utils/animate'; | |||||
class ChartComponent { | class ChartComponent { | ||||
constructor({ | constructor({ | ||||
@@ -11,14 +11,12 @@ class ChartComponent { | |||||
getData, | getData, | ||||
makeElements, | makeElements, | ||||
postMake, | |||||
animateElements | animateElements | ||||
}) { | }) { | ||||
this.layerTransform = layerTransform; | this.layerTransform = layerTransform; | ||||
this.constants = constants; | this.constants = constants; | ||||
this.makeElements = makeElements; | this.makeElements = makeElements; | ||||
this.postMake = postMake; | |||||
this.getData = getData; | this.getData = getData; | ||||
this.animateElements = animateElements; | this.animateElements = animateElements; | ||||
@@ -41,9 +39,7 @@ class ChartComponent { | |||||
} | } | ||||
make() { | make() { | ||||
this.preMake && this.preMake(); | |||||
this.render(this.data); | this.render(this.data); | ||||
this.postMake && this.postMake(); | |||||
this.oldData = this.data; | this.oldData = this.data; | ||||
} | } | ||||
@@ -81,8 +77,8 @@ let componentConfigs = { | |||||
}, | }, | ||||
animateElements(newData) { | animateElements(newData) { | ||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let oldPos = this.oldData.positions; | let oldPos = this.oldData.positions; | ||||
let oldLabels = this.oldData.labels; | let oldLabels = this.oldData.labels; | ||||
@@ -112,8 +108,8 @@ let componentConfigs = { | |||||
}, | }, | ||||
animateElements(newData) { | animateElements(newData) { | ||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let newPos = newData.positions; | |||||
let newLabels = newData.labels; | |||||
let oldPos = this.oldData.positions; | let oldPos = this.oldData.positions; | ||||
let oldLabels = this.oldData.labels; | let oldLabels = this.oldData.labels; | ||||
@@ -144,8 +140,8 @@ let componentConfigs = { | |||||
animateElements(newData) { | animateElements(newData) { | ||||
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | [this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | ||||
let newPos = newData.map(d => d.position); | |||||
let newLabels = newData.map(d => d.label); | |||||
let newPos = newData.map(d => d.position); | |||||
let newLabels = newData.map(d => d.label); | |||||
let oldPos = this.oldData.map(d => d.position); | let oldPos = this.oldData.map(d => d.position); | ||||
let oldLabels = this.oldData.map(d => d.label); | let oldLabels = this.oldData.map(d => d.label); | ||||
@@ -176,9 +172,9 @@ let componentConfigs = { | |||||
animateElements(newData) { | 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 oldPos = this.oldData.map(d => d.end); | ||||
let oldLabels = this.oldData.map(d => d.label); | let oldLabels = this.oldData.map(d => d.label); | ||||
@@ -209,57 +205,67 @@ let componentConfigs = { | |||||
makeElements(data) { | makeElements(data) { | ||||
let c = this.constants; | let c = this.constants; | ||||
return data.yPositions.map((y, j) => { | return data.yPositions.map((y, j) => { | ||||
// console.log(data.cumulativeYPos, data.cumulativeYPos[j]); | |||||
return datasetBar( | return datasetBar( | ||||
data.xPositions[j], | data.xPositions[j], | ||||
y, | y, | ||||
c.barWidth, | |||||
data.barWidth, | |||||
c.color, | c.color, | ||||
(c.valuesOverPoints ? (c.stacked ? data.cumulativeYs[j] : data.values[j]) : ''), | (c.valuesOverPoints ? (c.stacked ? data.cumulativeYs[j] : data.values[j]) : ''), | ||||
j, | j, | ||||
y - (c.stacked ? data.cumulativeYPos[j] : y), | y - (c.stacked ? data.cumulativeYPos[j] : y), | ||||
{ | { | ||||
zeroLine: c.zeroLine, | |||||
barsWidth: c.barsWidth, | |||||
zeroLine: data.zeroLine, | |||||
barsWidth: data.barsWidth, | |||||
minHeight: c.minHeight | minHeight: c.minHeight | ||||
} | } | ||||
) | ) | ||||
}); | }); | ||||
}, | }, | ||||
postMake() { | |||||
if((!this.constants.stacked)) { | |||||
this.layer.setAttribute('transform', | |||||
`translate(${this.constants.width * this.constants.index}, 0)`); | |||||
} | |||||
}, | |||||
animateElements(newData) { | animateElements(newData) { | ||||
// [this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | |||||
let c = this.constants; | |||||
let newXPos = newData.xPositions; | |||||
let newYPos = newData.yPositions; | |||||
let newCYPos = newData.cumulativeYPos; | |||||
let newValues = newData.values; | |||||
let newCYs = newData.cumulativeYs; | |||||
let oldXPos = this.oldData.xPositions; | |||||
let oldYPos = this.oldData.yPositions; | |||||
let oldCYPos = this.oldData.cumulativeYPos; | |||||
let oldValues = this.oldData.values; | |||||
let oldCYs = this.oldData.cumulativeYs; | |||||
[oldXPos, newXPos] = equilizeNoOfElements(oldXPos, newXPos); | |||||
[oldYPos, newYPos] = equilizeNoOfElements(oldYPos, newYPos); | |||||
[oldCYPos, newCYPos] = equilizeNoOfElements(oldCYPos, newCYPos); | |||||
[oldValues, newValues] = equilizeNoOfElements(oldValues, newValues); | |||||
[oldCYs, newCYs] = equilizeNoOfElements(oldCYs, newCYs); | |||||
// let newPos = newData.map(d => d.end); | |||||
// let newLabels = newData.map(d => d.label); | |||||
// let newStarts = newData.map(d => d.start); | |||||
this.render({ | |||||
xPositions: oldXPos, | |||||
yPositions: oldYPos, | |||||
cumulativeYPos: oldCYPos, | |||||
// let oldPos = this.oldData.map(d => d.end); | |||||
// let oldLabels = this.oldData.map(d => d.label); | |||||
// let oldStarts = this.oldData.map(d => d.start); | |||||
values: newValues, | |||||
cumulativeYs: newCYs, | |||||
// this.render(oldPos.map((pos, i) => { | |||||
// return { | |||||
// start: oldStarts[i], | |||||
// end: oldPos[i], | |||||
// label: newLabels[i] | |||||
// } | |||||
// })); | |||||
zeroLine: this.oldData.zeroLine, | |||||
barsWidth: this.oldData.barsWidth, | |||||
barWidth: this.oldData.barWidth, | |||||
}); | |||||
// let animateElements = []; | |||||
let animateElements = []; | |||||
// this.store.map((rectGroup, i) => { | |||||
// animateElements = animateElements.concat(animateRegion( | |||||
// rectGroup, newStarts[i], newPos[i], oldPos[i] | |||||
// )); | |||||
// }); | |||||
this.store.map((bar, i) => { | |||||
animateElements = animateElements.concat(animateBar( | |||||
bar, newXPos[i], newYPos[i], newData.barWidth, c.index, | |||||
{zeroLine: newData.zeroLine} | |||||
)); | |||||
}); | |||||
// return animateElements; | |||||
return animateElements; | |||||
} | } | ||||
}, | }, | ||||
@@ -269,7 +275,8 @@ let componentConfigs = { | |||||
} | } | ||||
export function getComponent(name, constants, getData) { | export function getComponent(name, constants, getData) { | ||||
let config = componentConfigs[name]; | |||||
let keys = Object.keys(componentConfigs).filter(k => name.includes(k)); | |||||
let config = componentConfigs[keys[0]]; | |||||
Object.assign(config, { | Object.assign(config, { | ||||
constants: constants, | constants: constants, | ||||
getData: getData | getData: getData | ||||
@@ -8,13 +8,14 @@ export const REPLACE_ALL_NEW_DUR = 250; | |||||
export const STD_EASING = 'easein'; | export const STD_EASING = 'easein'; | ||||
export function translate(unit, oldCoord, newCoord, duration) { | export function translate(unit, oldCoord, newCoord, duration) { | ||||
let old = typeof oldCoord === 'string' ? oldCoord : oldCoord.join(', '); | |||||
return [ | return [ | ||||
unit, | unit, | ||||
{transform: newCoord.join(', ')}, | {transform: newCoord.join(', ')}, | ||||
duration, | duration, | ||||
STD_EASING, | STD_EASING, | ||||
"translate", | "translate", | ||||
{transform: oldCoord.join(', ')} | |||||
{transform: old} | |||||
]; | ]; | ||||
} | } | ||||
@@ -41,6 +42,26 @@ export function animateRegion(rectGroup, newY1, newY2, oldY2) { | |||||
return [rectAnim, groupAnim]; | return [rectAnim, groupAnim]; | ||||
} | } | ||||
export function animateBar(bar, x, yTop, width, index=0, meta={}) { | |||||
let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine); | |||||
if(bar.nodeName !== 'rect') { | |||||
let rect = bar.childNodes[0]; | |||||
let rectAnim = [ | |||||
rect, | |||||
{width: width, height: height}, | |||||
UNIT_ANIM_DUR, | |||||
STD_EASING | |||||
] | |||||
let old = bar.getAttribute("transform").split("(")[1].slice(0, -1); | |||||
let groupAnim = translate(bar, old, [x, y], MARKER_LINE_ANIM_DUR); | |||||
return [rectAnim, groupAnim]; | |||||
} else { | |||||
return [[bar, {width: width, height: height, x: x, y: y}, UNIT_ANIM_DUR, STD_EASING]]; | |||||
} | |||||
// bar.animate({height: args.newHeight, y: yTop}, UNIT_ANIM_DUR, mina.easein); | |||||
} | |||||
export var Animator = (function() { | export var Animator = (function() { | ||||
var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) { | var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) { | ||||
// constants | // constants | ||||
@@ -2,7 +2,7 @@ import { fillArray } from './helpers'; | |||||
export function getBarHeightAndYAttr(yTop, zeroLine) { | export function getBarHeightAndYAttr(yTop, zeroLine) { | ||||
let height, y; | let height, y; | ||||
if (yTop < zeroLine) { | |||||
if (yTop <= zeroLine) { | |||||
height = zeroLine - yTop; | height = zeroLine - yTop; | ||||
y = yTop; | y = yTop; | ||||
} else { | } else { | ||||
@@ -363,31 +363,40 @@ export function yRegion(y1, y2, width, label) { | |||||
export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={}) { | export function datasetBar(x, yTop, width, color, label='', index=0, offset=0, meta={}) { | ||||
let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine); | let [height, y] = getBarHeightAndYAttr(yTop, meta.zeroLine); | ||||
// console.log(yTop, meta.zeroLine, y, offset); | // console.log(yTop, meta.zeroLine, y, offset); | ||||
y -= offset; | |||||
let rect = createSVG('rect', { | let rect = createSVG('rect', { | ||||
className: `bar mini`, | className: `bar mini`, | ||||
style: `fill: ${color}`, | style: `fill: ${color}`, | ||||
'data-point-index': index, | 'data-point-index': index, | ||||
x: x - meta.barsWidth/2, | |||||
y: y - offset, | |||||
x: x, | |||||
y: y, | |||||
width: width, | width: width, | ||||
height: height || meta.minHeight | |||||
height: height || meta.minHeight // TODO: correct y for positive min height | |||||
}); | }); | ||||
if(!label && !label.length) { | if(!label && !label.length) { | ||||
return rect; | return rect; | ||||
} else { | } else { | ||||
rect.setAttribute('y', 0); | |||||
rect.setAttribute('x', 0); | |||||
let text = createSVG('text', { | let text = createSVG('text', { | ||||
className: 'data-point-value', | className: 'data-point-value', | ||||
x: x, | |||||
y: y - offset, | |||||
x: width/2, | |||||
y: 0, | |||||
dy: (FONT_SIZE / 2 * -1) + 'px', | dy: (FONT_SIZE / 2 * -1) + 'px', | ||||
'font-size': FONT_SIZE + 'px', | 'font-size': FONT_SIZE + 'px', | ||||
'text-anchor': 'middle', | 'text-anchor': 'middle', | ||||
innerHTML: label | innerHTML: label | ||||
}); | }); | ||||
return wrapInSVGGroup([rect, text]); | |||||
let group = createSVG('g', { | |||||
transform: `translate(${x}, ${y})` | |||||
}); | |||||
group.appendChild(rect); | |||||
group.appendChild(text); | |||||
return group; | |||||
} | } | ||||
} | } | ||||