[animate] y regions

This commit is contained in:
Prateeksha Singh 2018-02-25 21:11:51 +05:30
parent 2224b2bb26
commit 84c8c17d72
13 changed files with 258 additions and 214 deletions

View File

@ -309,6 +309,21 @@ function translateHoriLine(yLine, newY, oldY) {
return translate(yLine, [0, oldY], [0, newY], MARKER_LINE_ANIM_DUR); 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 AXIS_TICK_LENGTH = 6;
const LABEL_MARGIN = 4; const LABEL_MARGIN = 4;
const FONT_SIZE = 10; const FONT_SIZE = 10;
@ -610,6 +625,44 @@ function yMarker(y, label, width, options={}) {
return line; 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 { class AxisChartRenderer {
constructor(state) { constructor(state) {
this.refreshState(state); this.refreshState(state);
@ -645,60 +698,6 @@ class AxisChartRenderer {
return region; 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) { animatebar(bar, x, yTop, index, noOfDatasets) {
let start = x - this.avgUnitWidth/4; let start = x - this.avgUnitWidth/4;
let width = (this.avgUnitWidth/2)/noOfDatasets; let width = (this.avgUnitWidth/2)/noOfDatasets;
@ -1166,6 +1165,11 @@ class BaseChart {
if(this.elementsToAnimate) { if(this.elementsToAnimate) {
runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate); runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate);
} }
// TODO: rebind new units
// if(this.isNavigable) {
// this.bind_units(units_array);
// }
} }
refreshComponents() {} refreshComponents() {}
@ -1412,15 +1416,14 @@ let componentConfigs = {
); );
}, },
animateElements: function(newData) { animateElements: function(newData) {
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData);
let newPos = newData.map(d => d.position); let newPos = newData.map(d => d.position);
let newLabels = newData.map(d => d.label); 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);
[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos);
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels);
this.render(oldPos.map((pos, i) => { this.render(oldPos.map((pos, i) => {
return { return {
position: oldPos[i], 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: { dataUnits: {
@ -2106,6 +2144,9 @@ class AxisChart extends BaseChart {
} }
if(s.yRegions) { if(s.yRegions) {
s.yRegions = s.yRegions.map(d => { 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.start = floatTwo(s.yAxis.zeroLine - d.start * s.yAxis.scaleMultiplier);
d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier); d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier);
return d; return d;
@ -2145,13 +2186,6 @@ class AxisChart extends BaseChart {
setupValues() {} setupValues() {}
initComponents() { initComponents() {
// TODO: rebind new units
// if(this.isNavigable) {
// this.bind_units(units_array);
// }
this.componentConfigs = [ this.componentConfigs = [
[ [
'yAxis', 'yAxis',
@ -2195,6 +2229,26 @@ class AxisChart extends BaseChart {
}.bind(this) }.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', 'yMarkers',
this.drawArea, this.drawArea,
@ -2212,19 +2266,8 @@ class AxisChart extends BaseChart {
function() { function() {
return this.state.yMarkers || []; return this.state.yMarkers || [];
}.bind(this) }.bind(this)
] ],
]; ];
// this.components = [
// yAxis
// // this.getXAxisComponents(),
// // ...this.getYRegions(),
// // ...this.getXRegions(),
// // ...this.getYMarkerLines(),
// // // ...this.getXMarkerLines(),
// // ...this.getChartComponents(),
// // ...this.getChartLabels(),
// ];
} }
setupComponents() { setupComponents() {
let optionals = ['yMarkers', 'yRegions']; let optionals = ['yMarkers', 'yRegions'];
@ -2253,11 +2296,6 @@ class AxisChart extends BaseChart {
return dataUnitsComponents; return dataUnitsComponents;
} }
getChartLabels() {
// To layer all labels above everything else
return [];
}
getDataUnitComponent(index, unitRenderer) { getDataUnitComponent(index, unitRenderer) {
return new ChartComponent({ return new ChartComponent({
layerClass: 'dataset-units dataset-' + index, 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() { refreshRenderer() {
// These args are basically the current state of the chart, // These args are basically the current state of the chart,
// with constant and alive params mixed // with constant and alive params mixed

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

@ -18,6 +18,14 @@ let bar_composite_data = {
} }
], ],
yRegions: [
{
label: "Region Y 1",
start: 100,
end: 300
},
],
datasets: [{ datasets: [{
"name": "Events", "name": "Events",
"values": report_count_list, "values": report_count_list,

View File

@ -215,6 +215,9 @@ export default class AxisChart extends BaseChart {
} }
if(s.yRegions) { if(s.yRegions) {
s.yRegions = s.yRegions.map(d => { 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.start = floatTwo(s.yAxis.zeroLine - d.start * s.yAxis.scaleMultiplier);
d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier); d.end = floatTwo(s.yAxis.zeroLine - d.end * s.yAxis.scaleMultiplier);
return d; return d;
@ -254,13 +257,6 @@ export default class AxisChart extends BaseChart {
setupValues() {} setupValues() {}
initComponents() { initComponents() {
// TODO: rebind new units
// if(this.isNavigable) {
// this.bind_units(units_array);
// }
this.componentConfigs = [ this.componentConfigs = [
[ [
'yAxis', 'yAxis',
@ -304,6 +300,26 @@ export default class AxisChart extends BaseChart {
}.bind(this) }.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', 'yMarkers',
this.drawArea, this.drawArea,
@ -321,19 +337,8 @@ export default class AxisChart extends BaseChart {
function() { function() {
return this.state.yMarkers || []; return this.state.yMarkers || [];
}.bind(this) }.bind(this)
] ],
]; ];
// this.components = [
// yAxis
// // this.getXAxisComponents(),
// // ...this.getYRegions(),
// // ...this.getXRegions(),
// // ...this.getYMarkerLines(),
// // // ...this.getXMarkerLines(),
// // ...this.getChartComponents(),
// // ...this.getChartLabels(),
// ];
} }
setupComponents() { setupComponents() {
let optionals = ['yMarkers', 'yRegions']; let optionals = ['yMarkers', 'yRegions'];
@ -362,11 +367,6 @@ export default class AxisChart extends BaseChart {
return dataUnitsComponents; return dataUnitsComponents;
} }
getChartLabels() {
// To layer all labels above everything else
return [];
}
getDataUnitComponent(index, unitRenderer) { getDataUnitComponent(index, unitRenderer) {
return new ChartComponent({ return new ChartComponent({
layerClass: 'dataset-units dataset-' + index, 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() { refreshRenderer() {
// These args are basically the current state of the chart, // These args are basically the current state of the chart,
// with constant and alive params mixed // with constant and alive params mixed

View File

@ -225,6 +225,11 @@ export default class BaseChart {
if(this.elementsToAnimate) { if(this.elementsToAnimate) {
runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate); runSMILAnimation(this.chartWrapper, this.svg, this.elementsToAnimate);
} }
// TODO: rebind new units
// if(this.isNavigable) {
// this.bind_units(units_array);
// }
} }
refreshComponents() {} refreshComponents() {}

View File

@ -1,7 +1,7 @@
import { makeSVGGroup } from '../utils/draw'; 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 { equilizeNoOfElements } from '../utils/draw-utils';
import { Animator, translateHoriLine, translateVertLine } from '../utils/animate'; import { Animator, translateHoriLine, translateVertLine, animateRegion } from '../utils/animate';
class ChartComponent { class ChartComponent {
constructor({ constructor({
@ -143,15 +143,14 @@ let componentConfigs = {
); );
}, },
animateElements: function(newData) { animateElements: function(newData) {
[this.oldData, newData] = equilizeNoOfElements(this.oldData, newData);
let newPos = newData.map(d => d.position); let newPos = newData.map(d => d.position);
let newLabels = newData.map(d => d.label); 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);
[oldPos, newPos] = equilizeNoOfElements(oldPos, newPos);
[oldLabels, newLabels] = equilizeNoOfElements(oldLabels, newLabels);
this.render(oldPos.map((pos, i) => { this.render(oldPos.map((pos, i) => {
return { return {
position: oldPos[i], 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: { dataUnits: {

View File

@ -26,6 +26,21 @@ export function translateHoriLine(yLine, newY, oldY) {
return translate(yLine, [0, oldY], [0, newY], MARKER_LINE_ANIM_DUR); 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() { export var Animator = (function() {
var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) { var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) {
// constants // constants

View File

@ -323,6 +323,44 @@ export function yMarker(y, label, width, options={}) {
return line; 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 { export class AxisChartRenderer {
constructor(state) { constructor(state) {
this.refreshState(state); this.refreshState(state);
@ -358,60 +396,6 @@ export class AxisChartRenderer {
return region; 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) { animatebar(bar, x, yTop, index, noOfDatasets) {
let start = x - this.avgUnitWidth/4; let start = x - this.avgUnitWidth/4;
let width = (this.avgUnitWidth/2)/noOfDatasets; let width = (this.avgUnitWidth/2)/noOfDatasets;