@@ -309,6 +309,21 @@ function translateHoriLine(yLine, newY, oldY) { | |||
return translate(yLine, [0, oldY], [0, newY], MARKER_LINE_ANIM_DUR); | |||
} | |||
function animateRegion(rectGroup, newY1, newY2, oldY2) { | |||
let newHeight = newY1 - newY2; | |||
let rect = rectGroup.childNodes[0]; | |||
let width = rect.getAttribute("width"); | |||
let rectAnim = [ | |||
rect, | |||
{ height: newHeight, 'stroke-dasharray': `${width}, ${newHeight}` }, | |||
MARKER_LINE_ANIM_DUR, | |||
STD_EASING | |||
]; | |||
let groupAnim = translate(rectGroup, [0, oldY2], [0, newY2], MARKER_LINE_ANIM_DUR); | |||
return [rectAnim, groupAnim]; | |||
} | |||
const AXIS_TICK_LENGTH = 6; | |||
const LABEL_MARGIN = 4; | |||
const FONT_SIZE = 10; | |||
@@ -610,6 +625,44 @@ function yMarker(y, label, width, options={}) { | |||
return line; | |||
} | |||
function yRegion(y1, y2, width, label) { | |||
// return a group | |||
let height = y1 - y2; | |||
let rect = createSVG('rect', { | |||
className: `bar mini`, // remove class | |||
styles: { | |||
fill: `rgba(228, 234, 239, 0.49)`, | |||
stroke: BASE_LINE_COLOR, | |||
'stroke-dasharray': `${width}, ${height}` | |||
}, | |||
// 'data-point-index': index, | |||
x: 0, | |||
y: 0, | |||
width: width, | |||
height: height | |||
}); | |||
let labelSvg = createSVG('text', { | |||
className: 'chart-label', | |||
x: width - getStringWidth(label, 4.5) - LABEL_MARGIN, | |||
y: 0, | |||
dy: (FONT_SIZE / -2) + 'px', | |||
'font-size': FONT_SIZE + 'px', | |||
'text-anchor': 'start', | |||
innerHTML: label+"" | |||
}); | |||
let region = createSVG('g', { | |||
transform: `translate(0, ${y2})` | |||
}); | |||
region.appendChild(rect); | |||
region.appendChild(labelSvg); | |||
return region; | |||
} | |||
class AxisChartRenderer { | |||
constructor(state) { | |||
this.refreshState(state); | |||
@@ -645,60 +698,6 @@ class AxisChartRenderer { | |||
return region; | |||
} | |||
yRegion(y1, y2, label) { | |||
// return a group | |||
let rect = createSVG('rect', { | |||
className: `bar mini`, // remove class | |||
style: `fill: rgba(228, 234, 239, 0.49)`, | |||
// 'data-point-index': index, | |||
x: 0, | |||
y: y2, | |||
width: this.totalWidth, | |||
height: y1 - y2 | |||
}); | |||
let upperBorder = createSVG('line', { | |||
className: 'line-horizontal', | |||
x1: 0, | |||
x2: this.totalWidth, | |||
y1: y2, | |||
y2: y2, | |||
styles: { | |||
stroke: BASE_LINE_COLOR | |||
} | |||
}); | |||
let lowerBorder = createSVG('line', { | |||
className: 'line-horizontal', | |||
x1: 0, | |||
x2: this.totalWidth, | |||
y1: y1, | |||
y2: y1, | |||
styles: { | |||
stroke: BASE_LINE_COLOR | |||
} | |||
}); | |||
let labelSvg = createSVG('text', { | |||
className: 'chart-label', | |||
x: this.totalWidth - getStringWidth(label, 4.5) - LABEL_MARGIN, | |||
y: y2 - FONT_SIZE - 2, | |||
dy: (FONT_SIZE / 2) + 'px', | |||
'font-size': FONT_SIZE + 'px', | |||
'text-anchor': 'start', | |||
innerHTML: label+"" | |||
}); | |||
let region = createSVG('g', {}); | |||
region.appendChild(rect); | |||
region.appendChild(upperBorder); | |||
region.appendChild(lowerBorder); | |||
region.appendChild(labelSvg); | |||
return region; | |||
} | |||
animatebar(bar, x, yTop, index, noOfDatasets) { | |||
let start = x - this.avgUnitWidth/4; | |||
let width = (this.avgUnitWidth/2)/noOfDatasets; | |||
@@ -1166,6 +1165,11 @@ class BaseChart { | |||
if(this.elementsToAnimate) { | |||
runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate); | |||
} | |||
// TODO: rebind new units | |||
// if(this.isNavigable) { | |||
// this.bind_units(units_array); | |||
// } | |||
} | |||
refreshComponents() {} | |||
@@ -1412,15 +1416,14 @@ let componentConfigs = { | |||
); | |||
}, | |||
animateElements: function(newData) { | |||
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | |||
let newPos = newData.map(d => d.position); | |||
let newLabels = newData.map(d => d.label); | |||
let oldPos = this.oldData.map(d => d.position); | |||
let oldLabels = this.oldData.map(d => d.label); | |||
[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos); | |||
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels); | |||
this.render(oldPos.map((pos, i) => { | |||
return { | |||
position: oldPos[i], | |||
@@ -1436,8 +1439,43 @@ let componentConfigs = { | |||
} | |||
}, | |||
yRegion: { | |||
// | |||
yRegions: { | |||
layerClass: 'y-regions', | |||
makeElements: function(data) { | |||
return data.map(region => | |||
yRegion(region.start, region.end, this.constants.width, | |||
region.label) | |||
); | |||
}, | |||
animateElements: function(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 oldPos = this.oldData.map(d => d.end); | |||
let oldLabels = this.oldData.map(d => d.label); | |||
let oldStarts = this.oldData.map(d => d.start); | |||
this.render(oldPos.map((pos, i) => { | |||
return { | |||
start: oldStarts[i], | |||
end: oldPos[i], | |||
label: newLabels[i] | |||
} | |||
})); | |||
let animateElements = []; | |||
this.store.map((rectGroup, i) => { | |||
animateElements = animateElements.concat(animateRegion( | |||
rectGroup, newStarts[i], newPos[i], oldPos[i] | |||
)); | |||
}); | |||
return animateElements; | |||
} | |||
}, | |||
dataUnits: { | |||
@@ -2106,6 +2144,9 @@ class AxisChart extends BaseChart { | |||
} | |||
if(s.yRegions) { | |||
s.yRegions = s.yRegions.map(d => { | |||
if(d.end < d.start) { | |||
[d.start, d.end] = [d.end, start]; | |||
} | |||
d.start = floatTwo(s.yAxis.zeroLine - d.start * s.yAxis.scaleMultiplier); | |||
d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier); | |||
return d; | |||
@@ -2145,13 +2186,6 @@ class AxisChart extends BaseChart { | |||
setupValues() {} | |||
initComponents() { | |||
// TODO: rebind new units | |||
// if(this.isNavigable) { | |||
// this.bind_units(units_array); | |||
// } | |||
this.componentConfigs = [ | |||
[ | |||
'yAxis', | |||
@@ -2195,6 +2229,26 @@ class AxisChart extends BaseChart { | |||
}.bind(this) | |||
], | |||
[ | |||
'yRegions', | |||
this.drawArea, | |||
{ | |||
// mode: this.yAxisMode, | |||
width: this.width, | |||
pos: 'right' | |||
}, | |||
[ | |||
{ | |||
start: this.height, | |||
end: this.height, | |||
label: '' | |||
} | |||
], | |||
function() { | |||
return this.state.yRegions || []; | |||
}.bind(this) | |||
], | |||
[ | |||
'yMarkers', | |||
this.drawArea, | |||
@@ -2212,19 +2266,8 @@ class AxisChart extends BaseChart { | |||
function() { | |||
return this.state.yMarkers || []; | |||
}.bind(this) | |||
] | |||
], | |||
]; | |||
// this.components = [ | |||
// yAxis | |||
// // this.getXAxisComponents(), | |||
// // ...this.getYRegions(), | |||
// // ...this.getXRegions(), | |||
// // ...this.getYMarkerLines(), | |||
// // // ...this.getXMarkerLines(), | |||
// // ...this.getChartComponents(), | |||
// // ...this.getChartLabels(), | |||
// ]; | |||
} | |||
setupComponents() { | |||
let optionals = ['yMarkers', 'yRegions']; | |||
@@ -2253,11 +2296,6 @@ class AxisChart extends BaseChart { | |||
return dataUnitsComponents; | |||
} | |||
getChartLabels() { | |||
// To layer all labels above everything else | |||
return []; | |||
} | |||
getDataUnitComponent(index, unitRenderer) { | |||
return new ChartComponent({ | |||
layerClass: 'dataset-units dataset-' + index, | |||
@@ -2367,26 +2405,6 @@ class AxisChart extends BaseChart { | |||
}); | |||
} | |||
getYRegions() { | |||
if(!this.data.yRegions) { | |||
return []; | |||
} | |||
// return []; | |||
return this.data.yRegions.map((d, index) => { | |||
return new ChartComponent({ | |||
layerClass: 'y-regions', | |||
setData: () => {}, | |||
makeElements: () => { | |||
let s = this.state; | |||
return s.yRegions.map(region => | |||
this.renderer.yRegion(region.start, region.end, region.name) | |||
); | |||
}, | |||
animate: () => {} | |||
}); | |||
}); | |||
} | |||
refreshRenderer() { | |||
// These args are basically the current state of the chart, | |||
// with constant and alive params mixed | |||
@@ -18,6 +18,14 @@ let bar_composite_data = { | |||
} | |||
], | |||
yRegions: [ | |||
{ | |||
label: "Region Y 1", | |||
start: 100, | |||
end: 300 | |||
}, | |||
], | |||
datasets: [{ | |||
"name": "Events", | |||
"values": report_count_list, | |||
@@ -215,6 +215,9 @@ export default class AxisChart extends BaseChart { | |||
} | |||
if(s.yRegions) { | |||
s.yRegions = s.yRegions.map(d => { | |||
if(d.end < d.start) { | |||
[d.start, d.end] = [d.end, start]; | |||
} | |||
d.start = floatTwo(s.yAxis.zeroLine - d.start * s.yAxis.scaleMultiplier); | |||
d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier); | |||
return d; | |||
@@ -254,13 +257,6 @@ export default class AxisChart extends BaseChart { | |||
setupValues() {} | |||
initComponents() { | |||
// TODO: rebind new units | |||
// if(this.isNavigable) { | |||
// this.bind_units(units_array); | |||
// } | |||
this.componentConfigs = [ | |||
[ | |||
'yAxis', | |||
@@ -304,6 +300,26 @@ export default class AxisChart extends BaseChart { | |||
}.bind(this) | |||
], | |||
[ | |||
'yRegions', | |||
this.drawArea, | |||
{ | |||
// mode: this.yAxisMode, | |||
width: this.width, | |||
pos: 'right' | |||
}, | |||
[ | |||
{ | |||
start: this.height, | |||
end: this.height, | |||
label: '' | |||
} | |||
], | |||
function() { | |||
return this.state.yRegions || []; | |||
}.bind(this) | |||
], | |||
[ | |||
'yMarkers', | |||
this.drawArea, | |||
@@ -321,19 +337,8 @@ export default class AxisChart extends BaseChart { | |||
function() { | |||
return this.state.yMarkers || []; | |||
}.bind(this) | |||
] | |||
], | |||
]; | |||
// this.components = [ | |||
// yAxis | |||
// // this.getXAxisComponents(), | |||
// // ...this.getYRegions(), | |||
// // ...this.getXRegions(), | |||
// // ...this.getYMarkerLines(), | |||
// // // ...this.getXMarkerLines(), | |||
// // ...this.getChartComponents(), | |||
// // ...this.getChartLabels(), | |||
// ]; | |||
} | |||
setupComponents() { | |||
let optionals = ['yMarkers', 'yRegions']; | |||
@@ -362,11 +367,6 @@ export default class AxisChart extends BaseChart { | |||
return dataUnitsComponents; | |||
} | |||
getChartLabels() { | |||
// To layer all labels above everything else | |||
return []; | |||
} | |||
getDataUnitComponent(index, unitRenderer) { | |||
return new ChartComponent({ | |||
layerClass: 'dataset-units dataset-' + index, | |||
@@ -476,26 +476,6 @@ export default class AxisChart extends BaseChart { | |||
}); | |||
} | |||
getYRegions() { | |||
if(!this.data.yRegions) { | |||
return []; | |||
} | |||
// return []; | |||
return this.data.yRegions.map((d, index) => { | |||
return new ChartComponent({ | |||
layerClass: 'y-regions', | |||
setData: () => {}, | |||
makeElements: () => { | |||
let s = this.state; | |||
return s.yRegions.map(region => | |||
this.renderer.yRegion(region.start, region.end, region.name) | |||
); | |||
}, | |||
animate: () => {} | |||
}); | |||
}); | |||
} | |||
refreshRenderer() { | |||
// These args are basically the current state of the chart, | |||
// with constant and alive params mixed | |||
@@ -225,6 +225,11 @@ export default class BaseChart { | |||
if(this.elementsToAnimate) { | |||
runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate); | |||
} | |||
// TODO: rebind new units | |||
// if(this.isNavigable) { | |||
// this.bind_units(units_array); | |||
// } | |||
} | |||
refreshComponents() {} | |||
@@ -1,7 +1,7 @@ | |||
import { makeSVGGroup } from '../utils/draw'; | |||
import { xLine, yLine, yMarker } from '../utils/draw'; | |||
import { xLine, yLine, yMarker, yRegion } from '../utils/draw'; | |||
import { equilizeNoOfElements } from '../utils/draw-utils'; | |||
import { Animator, translateHoriLine, translateVertLine } from '../utils/animate'; | |||
import { Animator, translateHoriLine, translateVertLine, animateRegion } from '../utils/animate'; | |||
class ChartComponent { | |||
constructor({ | |||
@@ -143,15 +143,14 @@ let componentConfigs = { | |||
); | |||
}, | |||
animateElements: function(newData) { | |||
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData); | |||
let newPos = newData.map(d => d.position); | |||
let newLabels = newData.map(d => d.label); | |||
let oldPos = this.oldData.map(d => d.position); | |||
let oldLabels = this.oldData.map(d => d.label); | |||
[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos); | |||
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels); | |||
this.render(oldPos.map((pos, i) => { | |||
return { | |||
position: oldPos[i], | |||
@@ -167,8 +166,43 @@ let componentConfigs = { | |||
} | |||
}, | |||
yRegion: { | |||
// | |||
yRegions: { | |||
layerClass: 'y-regions', | |||
makeElements: function(data) { | |||
return data.map(region => | |||
yRegion(region.start, region.end, this.constants.width, | |||
region.label) | |||
); | |||
}, | |||
animateElements: function(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 oldPos = this.oldData.map(d => d.end); | |||
let oldLabels = this.oldData.map(d => d.label); | |||
let oldStarts = this.oldData.map(d => d.start); | |||
this.render(oldPos.map((pos, i) => { | |||
return { | |||
start: oldStarts[i], | |||
end: oldPos[i], | |||
label: newLabels[i] | |||
} | |||
})); | |||
let animateElements = []; | |||
this.store.map((rectGroup, i) => { | |||
animateElements = animateElements.concat(animateRegion( | |||
rectGroup, newStarts[i], newPos[i], oldPos[i] | |||
)); | |||
}); | |||
return animateElements; | |||
} | |||
}, | |||
dataUnits: { | |||
@@ -26,6 +26,21 @@ export function translateHoriLine(yLine, newY, oldY) { | |||
return translate(yLine, [0, oldY], [0, newY], MARKER_LINE_ANIM_DUR); | |||
} | |||
export function animateRegion(rectGroup, newY1, newY2, oldY2) { | |||
let newHeight = newY1 - newY2; | |||
let rect = rectGroup.childNodes[0]; | |||
let width = rect.getAttribute("width"); | |||
let rectAnim = [ | |||
rect, | |||
{ height: newHeight, 'stroke-dasharray': `${width}, ${newHeight}` }, | |||
MARKER_LINE_ANIM_DUR, | |||
STD_EASING | |||
] | |||
let groupAnim = translate(rectGroup, [0, oldY2], [0, newY2], MARKER_LINE_ANIM_DUR); | |||
return [rectAnim, groupAnim]; | |||
} | |||
export var Animator = (function() { | |||
var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) { | |||
// constants | |||
@@ -323,6 +323,44 @@ export function yMarker(y, label, width, options={}) { | |||
return line; | |||
} | |||
export function yRegion(y1, y2, width, label) { | |||
// return a group | |||
let height = y1 - y2; | |||
let rect = createSVG('rect', { | |||
className: `bar mini`, // remove class | |||
styles: { | |||
fill: `rgba(228, 234, 239, 0.49)`, | |||
stroke: BASE_LINE_COLOR, | |||
'stroke-dasharray': `${width}, ${height}` | |||
}, | |||
// 'data-point-index': index, | |||
x: 0, | |||
y: 0, | |||
width: width, | |||
height: height | |||
}); | |||
let labelSvg = createSVG('text', { | |||
className: 'chart-label', | |||
x: width - getStringWidth(label, 4.5) - LABEL_MARGIN, | |||
y: 0, | |||
dy: (FONT_SIZE / -2) + 'px', | |||
'font-size': FONT_SIZE + 'px', | |||
'text-anchor': 'start', | |||
innerHTML: label+"" | |||
}); | |||
let region = createSVG('g', { | |||
transform: `translate(0, ${y2})` | |||
}); | |||
region.appendChild(rect); | |||
region.appendChild(labelSvg); | |||
return region; | |||
} | |||
export class AxisChartRenderer { | |||
constructor(state) { | |||
this.refreshState(state); | |||
@@ -358,60 +396,6 @@ export class AxisChartRenderer { | |||
return region; | |||
} | |||
yRegion(y1, y2, label) { | |||
// return a group | |||
let rect = createSVG('rect', { | |||
className: `bar mini`, // remove class | |||
style: `fill: rgba(228, 234, 239, 0.49)`, | |||
// 'data-point-index': index, | |||
x: 0, | |||
y: y2, | |||
width: this.totalWidth, | |||
height: y1 - y2 | |||
}); | |||
let upperBorder = createSVG('line', { | |||
className: 'line-horizontal', | |||
x1: 0, | |||
x2: this.totalWidth, | |||
y1: y2, | |||
y2: y2, | |||
styles: { | |||
stroke: BASE_LINE_COLOR | |||
} | |||
}); | |||
let lowerBorder = createSVG('line', { | |||
className: 'line-horizontal', | |||
x1: 0, | |||
x2: this.totalWidth, | |||
y1: y1, | |||
y2: y1, | |||
styles: { | |||
stroke: BASE_LINE_COLOR | |||
} | |||
}); | |||
let labelSvg = createSVG('text', { | |||
className: 'chart-label', | |||
x: this.totalWidth - getStringWidth(label, 4.5) - LABEL_MARGIN, | |||
y: y2 - FONT_SIZE - 2, | |||
dy: (FONT_SIZE / 2) + 'px', | |||
'font-size': FONT_SIZE + 'px', | |||
'text-anchor': 'start', | |||
innerHTML: label+"" | |||
}); | |||
let region = createSVG('g', {}); | |||
region.appendChild(rect); | |||
region.appendChild(upperBorder); | |||
region.appendChild(lowerBorder); | |||
region.appendChild(labelSvg); | |||
return region; | |||
} | |||
animatebar(bar, x, yTop, index, noOfDatasets) { | |||
let start = x - this.avgUnitWidth/4; | |||
let width = (this.avgUnitWidth/2)/noOfDatasets; | |||