[Axis] bind arrow keys
This commit is contained in:
parent
02a1c4c5cf
commit
49f362eb14
416
dist/frappe-charts.esm.js
vendored
416
dist/frappe-charts.esm.js
vendored
@ -1,20 +1,20 @@
|
|||||||
function $$1(expr, con) {
|
function $(expr, con) {
|
||||||
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
|
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$$1.create = (tag, o) => {
|
$.create = (tag, o) => {
|
||||||
var element = document.createElement(tag);
|
var element = document.createElement(tag);
|
||||||
|
|
||||||
for (var i in o) {
|
for (var i in o) {
|
||||||
var val = o[i];
|
var val = o[i];
|
||||||
|
|
||||||
if (i === "inside") {
|
if (i === "inside") {
|
||||||
$$1(val).appendChild(element);
|
$(val).appendChild(element);
|
||||||
}
|
}
|
||||||
else if (i === "around") {
|
else if (i === "around") {
|
||||||
var ref = $$1(val);
|
var ref = $(val);
|
||||||
ref.parentNode.insertBefore(element, ref);
|
ref.parentNode.insertBefore(element, ref);
|
||||||
element.appendChild(ref);
|
element.appendChild(ref);
|
||||||
|
|
||||||
@ -66,6 +66,22 @@ function getElementContentWidth(element) {
|
|||||||
return element.clientWidth - padding;
|
return element.clientWidth - padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function fire(target, type, properties) {
|
||||||
|
var evt = document.createEvent("HTMLEvents");
|
||||||
|
|
||||||
|
evt.initEvent(type, true, true );
|
||||||
|
|
||||||
|
for (var j in properties) {
|
||||||
|
evt[j] = properties[j];
|
||||||
|
}
|
||||||
|
|
||||||
|
return target.dispatchEvent(evt);
|
||||||
|
}
|
||||||
|
|
||||||
class SvgTip {
|
class SvgTip {
|
||||||
constructor({
|
constructor({
|
||||||
parent = null,
|
parent = null,
|
||||||
@ -98,7 +114,7 @@ class SvgTip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
make_tooltip() {
|
make_tooltip() {
|
||||||
this.container = $$1.create('div', {
|
this.container = $.create('div', {
|
||||||
inside: this.parent,
|
inside: this.parent,
|
||||||
className: 'graph-svg-tip comparison',
|
className: 'graph-svg-tip comparison',
|
||||||
innerHTML: `<span class="title"></span>
|
innerHTML: `<span class="title"></span>
|
||||||
@ -128,7 +144,7 @@ class SvgTip {
|
|||||||
this.list_values.map((set, i) => {
|
this.list_values.map((set, i) => {
|
||||||
const color = this.colors[i] || 'black';
|
const color = this.colors[i] || 'black';
|
||||||
|
|
||||||
let li = $$1.create('li', {
|
let li = $.create('li', {
|
||||||
styles: {
|
styles: {
|
||||||
'border-top': `3px solid ${color}`
|
'border-top': `3px solid ${color}`
|
||||||
},
|
},
|
||||||
@ -376,11 +392,39 @@ function animatePath(paths, newXList, newYList, zeroLine) {
|
|||||||
return pathComponents;
|
return pathComponents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Y_AXIS_MARGIN = 60;
|
||||||
|
|
||||||
|
const DEFAULT_AXIS_CHART_TYPE = 'line';
|
||||||
|
const AXIS_DATASET_CHART_TYPES = ['line', 'bar'];
|
||||||
|
|
||||||
|
const BAR_CHART_SPACE_RATIO = 0.5;
|
||||||
|
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||||
|
|
||||||
|
const LINE_CHART_DOT_SIZE = 4;
|
||||||
|
|
||||||
|
const DOT_OVERLAY_SIZE_INCR = 4;
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
<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;
|
||||||
const BASE_LINE_COLOR = '#dadada';
|
const BASE_LINE_COLOR = '#dadada';
|
||||||
function $$2(expr, con) {
|
function $$1(expr, con) {
|
||||||
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
|
return typeof expr === "string"? (con || document).querySelector(expr) : expr || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -391,10 +435,10 @@ function createSVG(tag, o) {
|
|||||||
var val = o[i];
|
var val = o[i];
|
||||||
|
|
||||||
if (i === "inside") {
|
if (i === "inside") {
|
||||||
$$2(val).appendChild(element);
|
$$1(val).appendChild(element);
|
||||||
}
|
}
|
||||||
else if (i === "around") {
|
else if (i === "around") {
|
||||||
var ref = $$2(val);
|
var ref = $$1(val);
|
||||||
ref.parentNode.insertBefore(element, ref);
|
ref.parentNode.insertBefore(element, ref);
|
||||||
element.appendChild(ref);
|
element.appendChild(ref);
|
||||||
|
|
||||||
@ -710,7 +754,6 @@ 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);
|
|
||||||
y -= offset;
|
y -= offset;
|
||||||
|
|
||||||
let rect = createSVG('rect', {
|
let rect = createSVG('rect', {
|
||||||
@ -810,6 +853,80 @@ function getPaths(xList, yList, color, options={}, meta={}) {
|
|||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let makeOverlay = {
|
||||||
|
'bar': (unit) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'rect') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let overlay = unit.cloneNode();
|
||||||
|
overlay.style.fill = '#000000';
|
||||||
|
overlay.style.opacity = '0.4';
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
return overlay;
|
||||||
|
},
|
||||||
|
|
||||||
|
'dot': (unit) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'circle') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let overlay = unit.cloneNode();
|
||||||
|
let radius = unit.getAttribute('r');
|
||||||
|
overlay.setAttribute('r', radius + DOT_OVERLAY_SIZE_INCR);
|
||||||
|
overlay.style.fill = '#000000';
|
||||||
|
overlay.style.opacity = '0.4';
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
return overlay;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let updateOverlay = {
|
||||||
|
'bar': (unit, overlay) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'rect') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let attributes = ['x', 'y', 'width', 'height'];
|
||||||
|
Object.values(unit.attributes)
|
||||||
|
.filter(attr => attributes.includes(attr.name) && attr.specified)
|
||||||
|
.map(attr => {
|
||||||
|
overlay.setAttribute(attr.name, attr.nodeValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'dot': (unit, overlay) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'circle') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let attributes = ['cx', 'cy'];
|
||||||
|
Object.values(unit.attributes)
|
||||||
|
.filter(attr => attributes.includes(attr.name) && attr.specified)
|
||||||
|
.map(attr => {
|
||||||
|
overlay.setAttribute(attr.name, attr.nodeValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const PRESET_COLOR_MAP = {
|
const PRESET_COLOR_MAP = {
|
||||||
'light-blue': '#7cd6fd',
|
'light-blue': '#7cd6fd',
|
||||||
'blue': '#5e64ff',
|
'blue': '#5e64ff',
|
||||||
@ -1046,30 +1163,28 @@ class BaseChart {
|
|||||||
this.argHeight = height;
|
this.argHeight = height;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
this.isNavigable = isNavigable;
|
|
||||||
if(this.isNavigable) {
|
|
||||||
this.currentIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.realData = this.prepareData(data);
|
this.realData = this.prepareData(data);
|
||||||
this.data = this.prepareFirstData(this.realData);
|
this.data = this.prepareFirstData(this.realData);
|
||||||
this.colors = [];
|
this.colors = [];
|
||||||
this.config = {};
|
this.config = {
|
||||||
|
showTooltip: 1, // calculate
|
||||||
|
showLegend: 1,
|
||||||
|
isNavigable: isNavigable,
|
||||||
|
animate: 1
|
||||||
|
};
|
||||||
this.state = {};
|
this.state = {};
|
||||||
this.options = {};
|
this.options = {};
|
||||||
|
|
||||||
|
if(this.config.isNavigable) {
|
||||||
|
this.state.currentIndex = 0;
|
||||||
|
this.overlays = [];
|
||||||
|
}
|
||||||
|
|
||||||
this.configure(arguments[0]);
|
this.configure(arguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(args) {
|
configure(args) {
|
||||||
this.setColors();
|
this.setColors();
|
||||||
this.config = {
|
|
||||||
showTooltip: 1, // calculate
|
|
||||||
showLegend: 1,
|
|
||||||
isNavigable: 0,
|
|
||||||
animate: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setMargins();
|
this.setMargins();
|
||||||
|
|
||||||
// Bind window events
|
// Bind window events
|
||||||
@ -1127,14 +1242,12 @@ class BaseChart {
|
|||||||
this.draw(true);
|
this.draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
initComponents() {}
|
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
this.components = new Map();
|
this.components = new Map();
|
||||||
}
|
}
|
||||||
|
|
||||||
makeContainer() {
|
makeContainer() {
|
||||||
this.container = $$1.create('div', {
|
this.container = $.create('div', {
|
||||||
className: 'chart-container',
|
className: 'chart-container',
|
||||||
innerHTML: `<h6 class="title">${this.title}</h6>
|
innerHTML: `<h6 class="title">${this.title}</h6>
|
||||||
<h6 class="sub-title uppercase">${this.subtitle}</h6>
|
<h6 class="sub-title uppercase">${this.subtitle}</h6>
|
||||||
@ -1164,21 +1277,19 @@ class BaseChart {
|
|||||||
this.calcWidth();
|
this.calcWidth();
|
||||||
this.calc();
|
this.calc();
|
||||||
this.makeChartArea();
|
this.makeChartArea();
|
||||||
this.initComponents();
|
|
||||||
|
|
||||||
this.setupComponents();
|
this.setupComponents();
|
||||||
|
|
||||||
this.components.forEach(c => c.setup(this.drawArea)); // or c.build()
|
this.components.forEach(c => c.setup(this.drawArea)); // or c.build()
|
||||||
this.components.forEach(c => c.make()); // or c.build()
|
this.components.forEach(c => c.make()); // or c.build()
|
||||||
|
|
||||||
this.renderLegend();
|
|
||||||
this.setupNavigation(init);
|
|
||||||
|
|
||||||
// TODO: remove timeout and decrease post animate time in chart component
|
// TODO: remove timeout and decrease post animate time in chart component
|
||||||
if(init) {
|
if(init) {
|
||||||
this.data = this.realData;
|
this.data = this.realData;
|
||||||
setTimeout(() => {this.update();}, 1000);
|
setTimeout(() => {this.update();}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.renderLegend();
|
||||||
|
this.setupNavigation(init);
|
||||||
}
|
}
|
||||||
|
|
||||||
calcWidth() {
|
calcWidth() {
|
||||||
@ -1205,19 +1316,37 @@ class BaseChart {
|
|||||||
calc() {} // builds state
|
calc() {} // builds state
|
||||||
|
|
||||||
render(components=this.components, animate=true) {
|
render(components=this.components, animate=true) {
|
||||||
// Can decouple to this.refreshComponents() first to save animation timeout
|
if(this.config.isNavigable) {
|
||||||
|
// Remove all existing overlays
|
||||||
|
this.overlays.map(o => o.parentNode.removeChild(o));
|
||||||
|
// ref.parentNode.insertBefore(element, ref);
|
||||||
|
}
|
||||||
let elementsToAnimate = [];
|
let elementsToAnimate = [];
|
||||||
|
// Can decouple to this.refreshComponents() first to save animation timeout
|
||||||
components.forEach(c => {
|
components.forEach(c => {
|
||||||
elementsToAnimate = elementsToAnimate.concat(c.update(animate));
|
elementsToAnimate = elementsToAnimate.concat(c.update(animate));
|
||||||
});
|
});
|
||||||
if(elementsToAnimate.length > 0) {
|
if(elementsToAnimate.length > 0) {
|
||||||
runSMILAnimation(this.chartWrapper, this.svg, elementsToAnimate);
|
runSMILAnimation(this.chartWrapper, this.svg, elementsToAnimate);
|
||||||
|
setTimeout(() => {
|
||||||
|
components.forEach(c => c.make());
|
||||||
|
this.updateNav();
|
||||||
|
}, 400);
|
||||||
|
} else {
|
||||||
|
this.updateNav();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: rebind new units
|
updateNav() {
|
||||||
// if(this.isNavigable) {
|
if(this.config.isNavigable) {
|
||||||
// this.bind_units(units_array);
|
// Make new overlays
|
||||||
// }
|
if(!this.overlayGuides){
|
||||||
|
this.makeOverlays();
|
||||||
|
this.bindUnits();
|
||||||
|
} else {
|
||||||
|
this.updateOverlays();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeChartArea() {
|
makeChartArea() {
|
||||||
@ -1249,36 +1378,31 @@ class BaseChart {
|
|||||||
renderLegend() {}
|
renderLegend() {}
|
||||||
|
|
||||||
setupNavigation(init=false) {
|
setupNavigation(init=false) {
|
||||||
if(this.isNavigable) return;
|
if(!this.config.isNavigable) return;
|
||||||
|
|
||||||
this.makeOverlay();
|
|
||||||
|
|
||||||
if(init) {
|
if(init) {
|
||||||
this.bindOverlay();
|
this.bindOverlay();
|
||||||
|
|
||||||
|
this.keyActions = {
|
||||||
|
'13': this.onEnterKey.bind(this),
|
||||||
|
'37': this.onLeftArrow.bind(this),
|
||||||
|
'38': this.onUpArrow.bind(this),
|
||||||
|
'39': this.onRightArrow.bind(this),
|
||||||
|
'40': this.onDownArrow.bind(this),
|
||||||
|
};
|
||||||
|
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if(isElementInViewport(this.chartWrapper)) {
|
if(isElementInViewport(this.chartWrapper)) {
|
||||||
e = e || window.event;
|
e = e || window.event;
|
||||||
|
this.keyActions[e.keyCode]();
|
||||||
if (e.keyCode == '37') {
|
|
||||||
this.onLeftArrow();
|
|
||||||
} else if (e.keyCode == '39') {
|
|
||||||
this.onRightArrow();
|
|
||||||
} else if (e.keyCode == '38') {
|
|
||||||
this.onUpArrow();
|
|
||||||
} else if (e.keyCode == '40') {
|
|
||||||
this.onDownArrow();
|
|
||||||
} else if (e.keyCode == '13') {
|
|
||||||
this.onEnterKey();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeOverlay() {}
|
makeOverlays() {}
|
||||||
bindOverlay() {}
|
bindOverlay() {}
|
||||||
bind_units() {}
|
bindUnits() {}
|
||||||
|
|
||||||
onLeftArrow() {}
|
onLeftArrow() {}
|
||||||
onRightArrow() {}
|
onRightArrow() {}
|
||||||
@ -1286,13 +1410,6 @@ class BaseChart {
|
|||||||
onDownArrow() {}
|
onDownArrow() {}
|
||||||
onEnterKey() {}
|
onEnterKey() {}
|
||||||
|
|
||||||
// ????????????
|
|
||||||
// Update the data here, then do relevant updates
|
|
||||||
// and drawing in child classes by overriding
|
|
||||||
// The Child chart will only know what a particular update means
|
|
||||||
// and what components are affected,
|
|
||||||
// BaseChart shouldn't be doing the animating
|
|
||||||
|
|
||||||
getDataPoint(index = 0) {}
|
getDataPoint(index = 0) {}
|
||||||
setCurrentDataPoint(point) {}
|
setCurrentDataPoint(point) {}
|
||||||
|
|
||||||
@ -1311,16 +1428,6 @@ class BaseChart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Y_AXIS_MARGIN = 60;
|
|
||||||
|
|
||||||
const DEFAULT_AXIS_CHART_TYPE = 'line';
|
|
||||||
const AXIS_DATASET_CHART_TYPES = ['line', 'bar'];
|
|
||||||
|
|
||||||
const BAR_CHART_SPACE_RATIO = 0.5;
|
|
||||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
|
||||||
|
|
||||||
const LINE_CHART_DOT_SIZE = 4;
|
|
||||||
|
|
||||||
function dataPrep(data, type) {
|
function dataPrep(data, type) {
|
||||||
data.labels = data.labels || [];
|
data.labels = data.labels || [];
|
||||||
|
|
||||||
@ -1465,10 +1572,6 @@ class ChartComponent$1 {
|
|||||||
if(animate) {
|
if(animate) {
|
||||||
animateElements = this.animateElements(this.data);
|
animateElements = this.animateElements(this.data);
|
||||||
}
|
}
|
||||||
// TODO: Can we remove this?
|
|
||||||
setTimeout(() => {
|
|
||||||
this.make();
|
|
||||||
}, 1400);
|
|
||||||
return animateElements;
|
return animateElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1608,9 +1711,10 @@ let componentConfigs = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
barGraph: {
|
barGraph: {
|
||||||
layerClass: function() { return 'dataset-units dataset-' + this.constants.index; },
|
layerClass: function() { return 'dataset-units dataset-bars dataset-' + this.constants.index; },
|
||||||
makeElements(data) {
|
makeElements(data) {
|
||||||
let c = this.constants;
|
let c = this.constants;
|
||||||
|
this.unitType = 'bar';
|
||||||
return data.yPositions.map((y, j) => {
|
return data.yPositions.map((y, j) => {
|
||||||
return datasetBar(
|
return datasetBar(
|
||||||
data.xPositions[j],
|
data.xPositions[j],
|
||||||
@ -1676,9 +1780,11 @@ let componentConfigs = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
lineGraph: {
|
lineGraph: {
|
||||||
layerClass: function() { return 'dataset-units dataset-' + this.constants.index; },
|
layerClass: function() { return 'dataset-units dataset-line dataset-' + this.constants.index; },
|
||||||
makeElements(data) {
|
makeElements(data) {
|
||||||
let c = this.constants;
|
let c = this.constants;
|
||||||
|
this.unitType = 'dot';
|
||||||
|
|
||||||
this.paths = getPaths(
|
this.paths = getPaths(
|
||||||
data.xPositions,
|
data.xPositions,
|
||||||
data.yPositions,
|
data.yPositions,
|
||||||
@ -1709,6 +1815,7 @@ let componentConfigs = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(this.paths).concat(this.dots);
|
return Object.values(this.paths).concat(this.dots);
|
||||||
|
// return this.dots;
|
||||||
},
|
},
|
||||||
animateElements(newData) {
|
animateElements(newData) {
|
||||||
let newXPos = newData.xPositions;
|
let newXPos = newData.xPositions;
|
||||||
@ -1992,9 +2099,6 @@ class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
configure(args) {3;
|
configure(args) {3;
|
||||||
super.configure();
|
super.configure();
|
||||||
|
|
||||||
// TODO: set in options and use
|
|
||||||
|
|
||||||
this.config.xAxisMode = args.xAxisMode;
|
this.config.xAxisMode = args.xAxisMode;
|
||||||
this.config.yAxisMode = args.yAxisMode;
|
this.config.yAxisMode = args.yAxisMode;
|
||||||
}
|
}
|
||||||
@ -2051,12 +2155,13 @@ class AxisChart extends BaseChart {
|
|||||||
zeroLine: zeroLine,
|
zeroLine: zeroLine,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.calcYUnits();
|
// Dependent if above changes
|
||||||
|
this.calcDatasetPoints();
|
||||||
this.calcYExtremes();
|
this.calcYExtremes();
|
||||||
this.calcYRegions();
|
this.calcYRegions();
|
||||||
}
|
}
|
||||||
|
|
||||||
calcYUnits() {
|
calcDatasetPoints() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
let scaleAll = values => values.map(val => scale(val, s.yAxis));
|
let scaleAll = values => values.map(val => scale(val, s.yAxis));
|
||||||
|
|
||||||
@ -2079,7 +2184,7 @@ class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
calcYExtremes() {
|
calcYExtremes() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
if(this.barOptions && this.barOptions.stacked) {
|
if(this.barOptions.stacked) {
|
||||||
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativeYPos;
|
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativeYPos;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -2115,7 +2220,7 @@ class AxisChart extends BaseChart {
|
|||||||
// TODO: yMarkers, regions, sums, every Y value ever
|
// TODO: yMarkers, regions, sums, every Y value ever
|
||||||
let key = 'values';
|
let key = 'values';
|
||||||
|
|
||||||
if(this.barOptions && this.barOptions.stacked) {
|
if(this.barOptions.stacked) {
|
||||||
key = 'cumulativeYs';
|
key = 'cumulativeYs';
|
||||||
let cumulative = new Array(this.state.datasetLength).fill(0);
|
let cumulative = new Array(this.state.datasetLength).fill(0);
|
||||||
this.data.datasets.map((d, i) => {
|
this.data.datasets.map((d, i) => {
|
||||||
@ -2127,8 +2232,8 @@ class AxisChart extends BaseChart {
|
|||||||
return [].concat(...this.data.datasets.map(d => d[key]));
|
return [].concat(...this.data.datasets.map(d => d[key]));
|
||||||
}
|
}
|
||||||
|
|
||||||
initComponents() {
|
setupComponents() {
|
||||||
this.componentConfigs = [
|
let componentConfigs = [
|
||||||
[
|
[
|
||||||
'yAxis',
|
'yAxis',
|
||||||
{
|
{
|
||||||
@ -2156,7 +2261,7 @@ class AxisChart extends BaseChart {
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
this.componentConfigs.map(args => {
|
componentConfigs.map(args => {
|
||||||
args.push(
|
args.push(
|
||||||
function() {
|
function() {
|
||||||
return this.state[args[0]];
|
return this.state[args[0]];
|
||||||
@ -2176,6 +2281,7 @@ class AxisChart extends BaseChart {
|
|||||||
{
|
{
|
||||||
index: index,
|
index: index,
|
||||||
color: this.colors[index],
|
color: this.colors[index],
|
||||||
|
stacked: this.barOptions.stacked,
|
||||||
|
|
||||||
// same for all datasets
|
// same for all datasets
|
||||||
valuesOverPoints: this.valuesOverPoints,
|
valuesOverPoints: this.valuesOverPoints,
|
||||||
@ -2189,7 +2295,10 @@ class AxisChart extends BaseChart {
|
|||||||
let barsWidth = s.unitWidth * (1 - spaceRatio);
|
let barsWidth = s.unitWidth * (1 - spaceRatio);
|
||||||
let barWidth = barsWidth/(this.barOptions.stacked ? 1 : barDatasets.length);
|
let barWidth = barsWidth/(this.barOptions.stacked ? 1 : barDatasets.length);
|
||||||
|
|
||||||
let xPositions = s.xAxis.positions.map(x => x - barsWidth/2 + barWidth * index);
|
let xPositions = s.xAxis.positions.map(x => x - barsWidth/2);
|
||||||
|
if(!this.barOptions.stacked) {
|
||||||
|
xPositions = xPositions.map(p => p + barWidth * index);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
xPositions: xPositions,
|
xPositions: xPositions,
|
||||||
@ -2257,15 +2366,19 @@ class AxisChart extends BaseChart {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.componentConfigs = this.componentConfigs.concat(barsConfigs, lineConfigs, markerConfigs);
|
componentConfigs = componentConfigs.concat(barsConfigs, lineConfigs, markerConfigs);
|
||||||
}
|
|
||||||
|
|
||||||
setupComponents() {
|
|
||||||
let optionals = ['yMarkers', 'yRegions'];
|
let optionals = ['yMarkers', 'yRegions'];
|
||||||
this.components = new Map(this.componentConfigs
|
this.dataUnitComponents = [];
|
||||||
.filter(args => !optionals.includes(args[0]) || this.state[args[0]] || args[0] === 'barGraph')
|
|
||||||
|
this.components = new Map(componentConfigs
|
||||||
|
.filter(args => !optionals.includes(args[0]) || this.state[args[0]])
|
||||||
.map(args => {
|
.map(args => {
|
||||||
return [args[0], getComponent(...args)];
|
let component = getComponent(...args);
|
||||||
|
if(args[0].includes('lineGraph') || args[0].includes('barGraph')) {
|
||||||
|
this.dataUnitComponents.push(component);
|
||||||
|
}
|
||||||
|
return [args[0], component];
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2317,27 +2430,91 @@ class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDataPoint(index=this.current_index) {
|
makeOverlays() {
|
||||||
|
// Just make one out of the first element
|
||||||
|
// let index = this.xAxisLabels.length - 1;
|
||||||
|
// let unit = this.y[0].svg_units[index];
|
||||||
|
// this.setCurrentDataPoint(index);
|
||||||
|
|
||||||
|
// if(this.overlay) {
|
||||||
|
// this.overlay.parentNode.removeChild(this.overlay);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.overlay = unit.cloneNode();
|
||||||
|
// this.overlay.style.fill = '#000000';
|
||||||
|
// this.overlay.style.opacity = '0.4';
|
||||||
|
// this.drawArea.appendChild(this.overlay);
|
||||||
|
this.overlayGuides = this.dataUnitComponents.map(c => {
|
||||||
|
return {
|
||||||
|
type: c.unitType,
|
||||||
|
overlay: undefined,
|
||||||
|
units: c.store,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.state.currentIndex = 0;
|
||||||
|
|
||||||
|
// Render overlays
|
||||||
|
this.overlayGuides.map(d => {
|
||||||
|
let currentUnit = d.units[this.state.currentIndex];
|
||||||
|
d.overlay = makeOverlay[d.type](currentUnit);
|
||||||
|
this.drawArea.appendChild(d.overlay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindOverlay() {
|
||||||
|
// on event, update overlay
|
||||||
|
this.parent.addEventListener('data-select', (e) => {
|
||||||
|
this.updateOverlay(e.svg_unit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindUnits(units_array) {
|
||||||
|
// units_array.map(unit => {
|
||||||
|
// unit.addEventListener('click', () => {
|
||||||
|
// let index = unit.getAttribute('data-point-index');
|
||||||
|
// this.setCurrentDataPoint(index);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOverlay() {
|
||||||
|
this.overlayGuides.map(d => {
|
||||||
|
let currentUnit = d.units[this.state.currentIndex];
|
||||||
|
updateOverlay[d.type](currentUnit, d.overlay);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
onLeftArrow() {
|
||||||
|
this.setCurrentDataPoint(this.state.currentIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRightArrow() {
|
||||||
|
this.setCurrentDataPoint(this.state.currentIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDataPoint(index=this.state.currentIndex) {
|
||||||
// check for length
|
// check for length
|
||||||
let data_point = {
|
let data_point = {
|
||||||
index: index
|
index: index
|
||||||
};
|
};
|
||||||
let y = this.y[0];
|
// let y = this.y[0];
|
||||||
['svg_units', 'yUnitPositions', 'values'].map(key => {
|
// ['svg_units', 'yUnitPositions', 'values'].map(key => {
|
||||||
let data_key = key.slice(0, key.length-1);
|
// let data_key = key.slice(0, key.length-1);
|
||||||
data_point[data_key] = y[key][index];
|
// data_point[data_key] = y[key][index];
|
||||||
});
|
// });
|
||||||
data_point.label = this.xAxis.labels[index];
|
// data_point.label = this.xAxis.labels[index];
|
||||||
return data_point;
|
return data_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentDataPoint(index) {
|
setCurrentDataPoint(index) {
|
||||||
|
let s = this.state;
|
||||||
index = parseInt(index);
|
index = parseInt(index);
|
||||||
if(index < 0) index = 0;
|
if(index < 0) index = 0;
|
||||||
if(index >= this.xAxis.labels.length) index = this.xAxis.labels.length - 1;
|
if(index >= s.xAxis.labels.length) index = s.xAxis.labels.length - 1;
|
||||||
if(index === this.current_index) return;
|
if(index === s.currentIndex) return;
|
||||||
this.current_index = index;
|
s.currentIndex = index;
|
||||||
$.fire(this.parent, "data-select", this.getDataPoint());
|
fire(this.parent, "data-select", this.getDataPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@ -2362,12 +2539,21 @@ class AxisChart extends BaseChart {
|
|||||||
this.update(this.data);
|
this.update(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateData() {
|
// getDataPoint(index = 0) {}
|
||||||
// // animate if same no. of datasets,
|
// setCurrentDataPoint(point) {}
|
||||||
// // else return new chart
|
|
||||||
|
|
||||||
// //
|
updateDataset(datasetValues, index=0) {
|
||||||
// }
|
this.data.datasets[index].values = datasetValues;
|
||||||
|
this.update(this.data);
|
||||||
|
}
|
||||||
|
// addDataset(dataset, index) {}
|
||||||
|
// removeDataset(index = 0) {}
|
||||||
|
|
||||||
|
// updateDatasets(datasets) {}
|
||||||
|
|
||||||
|
// updateDataPoint(dataPoint, index = 0) {}
|
||||||
|
// addDataPoint(dataPoint, index = 0) {}
|
||||||
|
// removeDataPoint(index = 0) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2561,19 +2747,19 @@ class PercentageChart extends BaseChart {
|
|||||||
this.statsWrapper.style.marginBottom = '30px';
|
this.statsWrapper.style.marginBottom = '30px';
|
||||||
this.statsWrapper.style.paddingTop = '0px';
|
this.statsWrapper.style.paddingTop = '0px';
|
||||||
|
|
||||||
this.chartDiv = $$1.create('div', {
|
this.chartDiv = $.create('div', {
|
||||||
className: 'div',
|
className: 'div',
|
||||||
inside: this.chartWrapper
|
inside: this.chartWrapper
|
||||||
});
|
});
|
||||||
|
|
||||||
this.chart = $$1.create('div', {
|
this.chart = $.create('div', {
|
||||||
className: 'progress-chart',
|
className: 'progress-chart',
|
||||||
inside: this.chartDiv
|
inside: this.chartDiv
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setupLayers() {
|
setupLayers() {
|
||||||
this.percentageBar = $$1.create('div', {
|
this.percentageBar = $.create('div', {
|
||||||
className: 'progress',
|
className: 'progress',
|
||||||
inside: this.chart
|
inside: this.chart
|
||||||
});
|
});
|
||||||
@ -2618,7 +2804,7 @@ class PercentageChart extends BaseChart {
|
|||||||
this.grand_total = this.slice_totals.reduce((a, b) => a + b, 0);
|
this.grand_total = this.slice_totals.reduce((a, b) => a + b, 0);
|
||||||
this.slices = [];
|
this.slices = [];
|
||||||
this.slice_totals.map((total, i) => {
|
this.slice_totals.map((total, i) => {
|
||||||
let slice = $$1.create('div', {
|
let slice = $.create('div', {
|
||||||
className: `progress-bar`,
|
className: `progress-bar`,
|
||||||
inside: this.percentageBar,
|
inside: this.percentageBar,
|
||||||
styles: {
|
styles: {
|
||||||
@ -2654,7 +2840,7 @@ class PercentageChart extends BaseChart {
|
|||||||
? this.formatted_labels : this.labels;
|
? this.formatted_labels : this.labels;
|
||||||
this.legend_totals.map((d, i) => {
|
this.legend_totals.map((d, i) => {
|
||||||
if(d) {
|
if(d) {
|
||||||
let stats = $$1.create('div', {
|
let stats = $.create('div', {
|
||||||
className: 'stats',
|
className: 'stats',
|
||||||
inside: this.statsWrapper
|
inside: this.statsWrapper
|
||||||
});
|
});
|
||||||
@ -2842,7 +3028,7 @@ class PieChart extends BaseChart {
|
|||||||
const color = this.colors[i];
|
const color = this.colors[i];
|
||||||
|
|
||||||
if(d) {
|
if(d) {
|
||||||
let stats = $$1.create('div', {
|
let stats = $.create('div', {
|
||||||
className: 'stats',
|
className: 'stats',
|
||||||
inside: this.statsWrapper
|
inside: this.statsWrapper
|
||||||
});
|
});
|
||||||
|
|||||||
2
dist/frappe-charts.min.cjs.js
vendored
2
dist/frappe-charts.min.cjs.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.esm.js
vendored
2
dist/frappe-charts.min.esm.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.iife.js
vendored
2
dist/frappe-charts.min.iife.js
vendored
File diff suppressed because one or more lines are too long
2
dist/frappe-charts.min.iife.js.map
vendored
2
dist/frappe-charts.min.iife.js.map
vendored
File diff suppressed because one or more lines are too long
2
docs/assets/js/frappe-charts.min.js
vendored
2
docs/assets/js/frappe-charts.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -42,22 +42,22 @@ let line_composite_data = {
|
|||||||
}]
|
}]
|
||||||
};
|
};
|
||||||
|
|
||||||
let more_line_data = {
|
let more_line_data = [
|
||||||
0: {values: [4, 0, 3, 1, 1, 2, 1, 2, 1, 0, 1, 1]},
|
[4, 0, 3, 1, 1, 2, 1, 2, 1, 0, 1, 1],
|
||||||
// 0: {values: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]},
|
// [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||||
1: {values: [2, 3, 3, 2, 1, 4, 0, 1, 2, 7, 11, 4]},
|
[2, 3, 3, 2, 1, 4, 0, 1, 2, 7, 11, 4],
|
||||||
2: {values: [7, 7, 2, 4, 0, 1, 5, 3, 1, 2, 0, 1]},
|
[7, 7, 2, 4, 0, 1, 5, 3, 1, 2, 0, 1],
|
||||||
3: {values: [0, 2, 6, 2, 2, 1, 2, 3, 6, 3, 7, 10]},
|
[0, 2, 6, 2, 2, 1, 2, 3, 6, 3, 7, 10],
|
||||||
4: {values: [9, 10, 8, 10, 6, 5, 8, 8, 24, 15, 10, 13]},
|
[9, 10, 8, 10, 6, 5, 8, 8, 24, 15, 10, 13],
|
||||||
5: {values: [9, 13, 16, 9, 4, 5, 7, 10, 14, 22, 23, 24]},
|
[9, 13, 16, 9, 4, 5, 7, 10, 14, 22, 23, 24],
|
||||||
6: {values: [20, 22, 28, 19, 28, 19, 14, 19, 51, 37, 29, 38]},
|
[20, 22, 28, 19, 28, 19, 14, 19, 51, 37, 29, 38],
|
||||||
7: {values: [29, 20, 22, 16, 16, 19, 24, 26, 57, 31, 46, 27]},
|
[29, 20, 22, 16, 16, 19, 24, 26, 57, 31, 46, 27],
|
||||||
8: {values: [36, 24, 38, 27, 15, 22, 24, 38, 32, 57, 139, 26]},
|
[36, 24, 38, 27, 15, 22, 24, 38, 32, 57, 139, 26],
|
||||||
9: {values: [37, 36, 32, 33, 12, 34, 52, 45, 58, 57, 64, 35]},
|
[37, 36, 32, 33, 12, 34, 52, 45, 58, 57, 64, 35],
|
||||||
10: {values: [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 0, 0]}
|
[36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 0, 0],
|
||||||
// 10: {values: [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 40, 40]}
|
// [36, 46, 45, 32, 27, 31, 30, 36, 39, 49, 40, 40]
|
||||||
// 10: {values: [-36, -46, -45, -32, -27, -31, -30, -36, -39, -49, -40, -40]}
|
// [-36, -46, -45, -32, -27, -31, -30, -36, -39, -49, -40, -40]
|
||||||
};
|
];
|
||||||
|
|
||||||
let c1 = document.querySelector("#chart-composite-1");
|
let c1 = document.querySelector("#chart-composite-1");
|
||||||
let c2 = document.querySelector("#chart-composite-2");
|
let c2 = document.querySelector("#chart-composite-2");
|
||||||
@ -89,39 +89,8 @@ let line_composite_chart = new Chart ({
|
|||||||
valuesOverPoints: 1,
|
valuesOverPoints: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Assuming this data structure for all, what would the most used APIs?
|
|
||||||
|
|
||||||
// chart.updateDataset([], index)
|
|
||||||
|
|
||||||
// chart.updateDatasets([[], [], []])
|
|
||||||
|
|
||||||
// chart.addDataset([], index)
|
|
||||||
|
|
||||||
// chart.removeDatasets(index)
|
|
||||||
|
|
||||||
// chart.addDataPoint({'asd': [20, 10, 30]})
|
|
||||||
|
|
||||||
// chart.removeDataPoint(index)
|
|
||||||
|
|
||||||
// chart.updatePoint('asd': [20, 10, 30]}, index)
|
|
||||||
|
|
||||||
// chart.update(data)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// let bar_update = [];
|
|
||||||
|
|
||||||
// setInterval(() => {
|
|
||||||
// line_composite_data.datasets = [more_line_data[5]];
|
|
||||||
// line_composite_chart.update(line_composite_data);
|
|
||||||
|
|
||||||
// bar_composite_data.datasets = [more_line_data[5]];
|
|
||||||
// bar_composite_chart.update(bar_composite_data);
|
|
||||||
// }, 2000);
|
|
||||||
|
|
||||||
bar_composite_chart.parent.addEventListener('data-select', (e) => {
|
bar_composite_chart.parent.addEventListener('data-select', (e) => {
|
||||||
line_composite_chart.updateData([more_line_data[e.index]]);
|
line_composite_chart.updateDataset(more_line_data[e.index]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@ -177,7 +146,7 @@ let type_data = {
|
|||||||
{
|
{
|
||||||
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: 'bar'
|
chartType: 'line'
|
||||||
}
|
}
|
||||||
|
|
||||||
// temp : Stacked
|
// temp : Stacked
|
||||||
|
|||||||
@ -5,6 +5,7 @@ import { getComponent } from '../objects/ChartComponents';
|
|||||||
import { getOffset, fire } from '../utils/dom';
|
import { getOffset, fire } from '../utils/dom';
|
||||||
import { calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex, scale } from '../utils/intervals';
|
import { calcChartIntervals, getIntervalSize, getValueRange, getZeroIndex, scale } from '../utils/intervals';
|
||||||
import { floatTwo } from '../utils/helpers';
|
import { floatTwo } from '../utils/helpers';
|
||||||
|
import { makeOverlay, updateOverlay } from '../utils/draw';
|
||||||
import { MIN_BAR_PERCENT_HEIGHT, DEFAULT_AXIS_CHART_TYPE, BAR_CHART_SPACE_RATIO, LINE_CHART_DOT_SIZE } from '../utils/constants';
|
import { MIN_BAR_PERCENT_HEIGHT, DEFAULT_AXIS_CHART_TYPE, BAR_CHART_SPACE_RATIO, LINE_CHART_DOT_SIZE } from '../utils/constants';
|
||||||
|
|
||||||
export default class AxisChart extends BaseChart {
|
export default class AxisChart extends BaseChart {
|
||||||
@ -28,9 +29,6 @@ export default class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
configure(args) {3
|
configure(args) {3
|
||||||
super.configure();
|
super.configure();
|
||||||
|
|
||||||
// TODO: set in options and use
|
|
||||||
|
|
||||||
this.config.xAxisMode = args.xAxisMode;
|
this.config.xAxisMode = args.xAxisMode;
|
||||||
this.config.yAxisMode = args.yAxisMode;
|
this.config.yAxisMode = args.yAxisMode;
|
||||||
}
|
}
|
||||||
@ -87,12 +85,13 @@ export default class AxisChart extends BaseChart {
|
|||||||
zeroLine: zeroLine,
|
zeroLine: zeroLine,
|
||||||
}
|
}
|
||||||
|
|
||||||
this.calcYUnits();
|
// Dependent if above changes
|
||||||
|
this.calcDatasetPoints();
|
||||||
this.calcYExtremes();
|
this.calcYExtremes();
|
||||||
this.calcYRegions();
|
this.calcYRegions();
|
||||||
}
|
}
|
||||||
|
|
||||||
calcYUnits() {
|
calcDatasetPoints() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
let scaleAll = values => values.map(val => scale(val, s.yAxis));
|
let scaleAll = values => values.map(val => scale(val, s.yAxis));
|
||||||
|
|
||||||
@ -115,7 +114,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
calcYExtremes() {
|
calcYExtremes() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
if(this.barOptions && this.barOptions.stacked) {
|
if(this.barOptions.stacked) {
|
||||||
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativeYPos;
|
s.yExtremes = s.datasets[s.datasets.length - 1].cumulativeYPos;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -151,7 +150,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
// TODO: yMarkers, regions, sums, every Y value ever
|
// TODO: yMarkers, regions, sums, every Y value ever
|
||||||
let key = 'values';
|
let key = 'values';
|
||||||
|
|
||||||
if(this.barOptions && this.barOptions.stacked) {
|
if(this.barOptions.stacked) {
|
||||||
key = 'cumulativeYs';
|
key = 'cumulativeYs';
|
||||||
let cumulative = new Array(this.state.datasetLength).fill(0);
|
let cumulative = new Array(this.state.datasetLength).fill(0);
|
||||||
this.data.datasets.map((d, i) => {
|
this.data.datasets.map((d, i) => {
|
||||||
@ -163,11 +162,9 @@ export default class AxisChart extends BaseChart {
|
|||||||
return [].concat(...this.data.datasets.map(d => d[key]));
|
return [].concat(...this.data.datasets.map(d => d[key]));
|
||||||
}
|
}
|
||||||
|
|
||||||
initComponents() {
|
setupComponents() {
|
||||||
let s = this.state;
|
let s = this.state;
|
||||||
// console.log('this.state', Object.assign({}, this.state));
|
let componentConfigs = [
|
||||||
// console.log('this.state', this.state);
|
|
||||||
this.componentConfigs = [
|
|
||||||
[
|
[
|
||||||
'yAxis',
|
'yAxis',
|
||||||
{
|
{
|
||||||
@ -195,7 +192,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
this.componentConfigs.map(args => {
|
componentConfigs.map(args => {
|
||||||
args.push(
|
args.push(
|
||||||
function() {
|
function() {
|
||||||
return this.state[args[0]];
|
return this.state[args[0]];
|
||||||
@ -215,6 +212,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
{
|
{
|
||||||
index: index,
|
index: index,
|
||||||
color: this.colors[index],
|
color: this.colors[index],
|
||||||
|
stacked: this.barOptions.stacked,
|
||||||
|
|
||||||
// same for all datasets
|
// same for all datasets
|
||||||
valuesOverPoints: this.valuesOverPoints,
|
valuesOverPoints: this.valuesOverPoints,
|
||||||
@ -228,7 +226,10 @@ export default class AxisChart extends BaseChart {
|
|||||||
let barsWidth = s.unitWidth * (1 - spaceRatio);
|
let barsWidth = s.unitWidth * (1 - spaceRatio);
|
||||||
let barWidth = barsWidth/(this.barOptions.stacked ? 1 : barDatasets.length);
|
let barWidth = barsWidth/(this.barOptions.stacked ? 1 : barDatasets.length);
|
||||||
|
|
||||||
let xPositions = s.xAxis.positions.map(x => x - barsWidth/2 + barWidth * index);
|
let xPositions = s.xAxis.positions.map(x => x - barsWidth/2);
|
||||||
|
if(!this.barOptions.stacked) {
|
||||||
|
xPositions = xPositions.map(p => p + barWidth * index);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
xPositions: xPositions,
|
xPositions: xPositions,
|
||||||
@ -296,15 +297,19 @@ export default class AxisChart extends BaseChart {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.componentConfigs = this.componentConfigs.concat(barsConfigs, lineConfigs, markerConfigs);
|
componentConfigs = componentConfigs.concat(barsConfigs, lineConfigs, markerConfigs);
|
||||||
}
|
|
||||||
|
|
||||||
setupComponents() {
|
|
||||||
let optionals = ['yMarkers', 'yRegions'];
|
let optionals = ['yMarkers', 'yRegions'];
|
||||||
this.components = new Map(this.componentConfigs
|
this.dataUnitComponents = [];
|
||||||
.filter(args => !optionals.includes(args[0]) || this.state[args[0]] || args[0] === 'barGraph')
|
|
||||||
|
this.components = new Map(componentConfigs
|
||||||
|
.filter(args => !optionals.includes(args[0]) || this.state[args[0]])
|
||||||
.map(args => {
|
.map(args => {
|
||||||
return [args[0], getComponent(...args)];
|
let component = getComponent(...args);
|
||||||
|
if(args[0].includes('lineGraph') || args[0].includes('barGraph')) {
|
||||||
|
this.dataUnitComponents.push(component);
|
||||||
|
}
|
||||||
|
return [args[0], component];
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,27 +361,91 @@ export default class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getDataPoint(index=this.current_index) {
|
makeOverlays() {
|
||||||
|
// Just make one out of the first element
|
||||||
|
// let index = this.xAxisLabels.length - 1;
|
||||||
|
// let unit = this.y[0].svg_units[index];
|
||||||
|
// this.setCurrentDataPoint(index);
|
||||||
|
|
||||||
|
// if(this.overlay) {
|
||||||
|
// this.overlay.parentNode.removeChild(this.overlay);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// this.overlay = unit.cloneNode();
|
||||||
|
// this.overlay.style.fill = '#000000';
|
||||||
|
// this.overlay.style.opacity = '0.4';
|
||||||
|
// this.drawArea.appendChild(this.overlay);
|
||||||
|
this.overlayGuides = this.dataUnitComponents.map(c => {
|
||||||
|
return {
|
||||||
|
type: c.unitType,
|
||||||
|
overlay: undefined,
|
||||||
|
units: c.store,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.state.currentIndex = 0;
|
||||||
|
|
||||||
|
// Render overlays
|
||||||
|
this.overlayGuides.map(d => {
|
||||||
|
let currentUnit = d.units[this.state.currentIndex];
|
||||||
|
d.overlay = makeOverlay[d.type](currentUnit);
|
||||||
|
this.drawArea.appendChild(d.overlay);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
bindOverlay() {
|
||||||
|
// on event, update overlay
|
||||||
|
this.parent.addEventListener('data-select', (e) => {
|
||||||
|
this.updateOverlay(e.svg_unit);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bindUnits(units_array) {
|
||||||
|
// units_array.map(unit => {
|
||||||
|
// unit.addEventListener('click', () => {
|
||||||
|
// let index = unit.getAttribute('data-point-index');
|
||||||
|
// this.setCurrentDataPoint(index);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
}
|
||||||
|
|
||||||
|
updateOverlay() {
|
||||||
|
this.overlayGuides.map(d => {
|
||||||
|
let currentUnit = d.units[this.state.currentIndex];
|
||||||
|
updateOverlay[d.type](currentUnit, d.overlay);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
onLeftArrow() {
|
||||||
|
this.setCurrentDataPoint(this.state.currentIndex - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
onRightArrow() {
|
||||||
|
this.setCurrentDataPoint(this.state.currentIndex + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDataPoint(index=this.state.currentIndex) {
|
||||||
// check for length
|
// check for length
|
||||||
let data_point = {
|
let data_point = {
|
||||||
index: index
|
index: index
|
||||||
};
|
};
|
||||||
let y = this.y[0];
|
// let y = this.y[0];
|
||||||
['svg_units', 'yUnitPositions', 'values'].map(key => {
|
// ['svg_units', 'yUnitPositions', 'values'].map(key => {
|
||||||
let data_key = key.slice(0, key.length-1);
|
// let data_key = key.slice(0, key.length-1);
|
||||||
data_point[data_key] = y[key][index];
|
// data_point[data_key] = y[key][index];
|
||||||
});
|
// });
|
||||||
data_point.label = this.xAxis.labels[index];
|
// data_point.label = this.xAxis.labels[index];
|
||||||
return data_point;
|
return data_point;
|
||||||
}
|
}
|
||||||
|
|
||||||
setCurrentDataPoint(index) {
|
setCurrentDataPoint(index) {
|
||||||
|
let s = this.state;
|
||||||
index = parseInt(index);
|
index = parseInt(index);
|
||||||
if(index < 0) index = 0;
|
if(index < 0) index = 0;
|
||||||
if(index >= this.xAxis.labels.length) index = this.xAxis.labels.length - 1;
|
if(index >= s.xAxis.labels.length) index = s.xAxis.labels.length - 1;
|
||||||
if(index === this.current_index) return;
|
if(index === s.currentIndex) return;
|
||||||
this.current_index = index;
|
s.currentIndex = index;
|
||||||
$.fire(this.parent, "data-select", this.getDataPoint());
|
fire(this.parent, "data-select", this.getDataPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
// API
|
// API
|
||||||
@ -401,12 +470,21 @@ export default class AxisChart extends BaseChart {
|
|||||||
this.update(this.data);
|
this.update(this.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateData() {
|
// getDataPoint(index = 0) {}
|
||||||
// // animate if same no. of datasets,
|
// setCurrentDataPoint(point) {}
|
||||||
// // else return new chart
|
|
||||||
|
|
||||||
// //
|
updateDataset(datasetValues, index=0) {
|
||||||
// }
|
this.data.datasets[index].values = datasetValues;
|
||||||
|
this.update(this.data);
|
||||||
|
}
|
||||||
|
// addDataset(dataset, index) {}
|
||||||
|
// removeDataset(index = 0) {}
|
||||||
|
|
||||||
|
// updateDatasets(datasets) {}
|
||||||
|
|
||||||
|
// updateDataPoint(dataPoint, index = 0) {}
|
||||||
|
// addDataPoint(dataPoint, index = 0) {}
|
||||||
|
// removeDataPoint(index = 0) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -30,30 +30,28 @@ export default class BaseChart {
|
|||||||
this.argHeight = height;
|
this.argHeight = height;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
|
|
||||||
this.isNavigable = isNavigable;
|
|
||||||
if(this.isNavigable) {
|
|
||||||
this.currentIndex = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.realData = this.prepareData(data);
|
this.realData = this.prepareData(data);
|
||||||
this.data = this.prepareFirstData(this.realData);
|
this.data = this.prepareFirstData(this.realData);
|
||||||
this.colors = [];
|
this.colors = [];
|
||||||
this.config = {};
|
this.config = {
|
||||||
|
showTooltip: 1, // calculate
|
||||||
|
showLegend: 1,
|
||||||
|
isNavigable: isNavigable,
|
||||||
|
animate: 1
|
||||||
|
};
|
||||||
this.state = {};
|
this.state = {};
|
||||||
this.options = {};
|
this.options = {};
|
||||||
|
|
||||||
|
if(this.config.isNavigable) {
|
||||||
|
this.state.currentIndex = 0;
|
||||||
|
this.overlays = [];
|
||||||
|
}
|
||||||
|
|
||||||
this.configure(arguments[0]);
|
this.configure(arguments[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
configure(args) {
|
configure(args) {
|
||||||
this.setColors();
|
this.setColors();
|
||||||
this.config = {
|
|
||||||
showTooltip: 1, // calculate
|
|
||||||
showLegend: 1,
|
|
||||||
isNavigable: 0,
|
|
||||||
animate: 1
|
|
||||||
};
|
|
||||||
|
|
||||||
this.setMargins();
|
this.setMargins();
|
||||||
|
|
||||||
// Bind window events
|
// Bind window events
|
||||||
@ -113,8 +111,6 @@ export default class BaseChart {
|
|||||||
this.draw(true);
|
this.draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
initComponents() {}
|
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
this.components = new Map();
|
this.components = new Map();
|
||||||
}
|
}
|
||||||
@ -150,21 +146,19 @@ export default class BaseChart {
|
|||||||
this.calcWidth();
|
this.calcWidth();
|
||||||
this.calc();
|
this.calc();
|
||||||
this.makeChartArea();
|
this.makeChartArea();
|
||||||
this.initComponents();
|
|
||||||
|
|
||||||
this.setupComponents();
|
this.setupComponents();
|
||||||
|
|
||||||
this.components.forEach(c => c.setup(this.drawArea)); // or c.build()
|
this.components.forEach(c => c.setup(this.drawArea)); // or c.build()
|
||||||
this.components.forEach(c => c.make()); // or c.build()
|
this.components.forEach(c => c.make()); // or c.build()
|
||||||
|
|
||||||
this.renderLegend();
|
|
||||||
this.setupNavigation(init);
|
|
||||||
|
|
||||||
// TODO: remove timeout and decrease post animate time in chart component
|
// TODO: remove timeout and decrease post animate time in chart component
|
||||||
if(init) {
|
if(init) {
|
||||||
this.data = this.realData;
|
this.data = this.realData;
|
||||||
setTimeout(() => {this.update();}, 1000);
|
setTimeout(() => {this.update();}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.renderLegend();
|
||||||
|
this.setupNavigation(init);
|
||||||
}
|
}
|
||||||
|
|
||||||
calcWidth() {
|
calcWidth() {
|
||||||
@ -191,19 +185,37 @@ export default class BaseChart {
|
|||||||
calc() {} // builds state
|
calc() {} // builds state
|
||||||
|
|
||||||
render(components=this.components, animate=true) {
|
render(components=this.components, animate=true) {
|
||||||
// Can decouple to this.refreshComponents() first to save animation timeout
|
if(this.config.isNavigable) {
|
||||||
|
// Remove all existing overlays
|
||||||
|
this.overlays.map(o => o.parentNode.removeChild(o));
|
||||||
|
// ref.parentNode.insertBefore(element, ref);
|
||||||
|
}
|
||||||
let elementsToAnimate = [];
|
let elementsToAnimate = [];
|
||||||
|
// Can decouple to this.refreshComponents() first to save animation timeout
|
||||||
components.forEach(c => {
|
components.forEach(c => {
|
||||||
elementsToAnimate = elementsToAnimate.concat(c.update(animate));
|
elementsToAnimate = elementsToAnimate.concat(c.update(animate));
|
||||||
});
|
});
|
||||||
if(elementsToAnimate.length > 0) {
|
if(elementsToAnimate.length > 0) {
|
||||||
runSMILAnimation(this.chartWrapper, this.svg, elementsToAnimate);
|
runSMILAnimation(this.chartWrapper, this.svg, elementsToAnimate);
|
||||||
|
setTimeout(() => {
|
||||||
|
components.forEach(c => c.make());
|
||||||
|
this.updateNav();
|
||||||
|
}, 400);
|
||||||
|
} else {
|
||||||
|
this.updateNav();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: rebind new units
|
updateNav() {
|
||||||
// if(this.isNavigable) {
|
if(this.config.isNavigable) {
|
||||||
// this.bind_units(units_array);
|
// Make new overlays
|
||||||
// }
|
if(!this.overlayGuides){
|
||||||
|
this.makeOverlays();
|
||||||
|
this.bindUnits();
|
||||||
|
} else {
|
||||||
|
this.updateOverlays();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeChartArea() {
|
makeChartArea() {
|
||||||
@ -235,36 +247,31 @@ export default class BaseChart {
|
|||||||
renderLegend() {}
|
renderLegend() {}
|
||||||
|
|
||||||
setupNavigation(init=false) {
|
setupNavigation(init=false) {
|
||||||
if(this.isNavigable) return;
|
if(!this.config.isNavigable) return;
|
||||||
|
|
||||||
this.makeOverlay();
|
|
||||||
|
|
||||||
if(init) {
|
if(init) {
|
||||||
this.bindOverlay();
|
this.bindOverlay();
|
||||||
|
|
||||||
|
this.keyActions = {
|
||||||
|
'13': this.onEnterKey.bind(this),
|
||||||
|
'37': this.onLeftArrow.bind(this),
|
||||||
|
'38': this.onUpArrow.bind(this),
|
||||||
|
'39': this.onRightArrow.bind(this),
|
||||||
|
'40': this.onDownArrow.bind(this),
|
||||||
|
}
|
||||||
|
|
||||||
document.addEventListener('keydown', (e) => {
|
document.addEventListener('keydown', (e) => {
|
||||||
if(isElementInViewport(this.chartWrapper)) {
|
if(isElementInViewport(this.chartWrapper)) {
|
||||||
e = e || window.event;
|
e = e || window.event;
|
||||||
|
this.keyActions[e.keyCode]();
|
||||||
if (e.keyCode == '37') {
|
|
||||||
this.onLeftArrow();
|
|
||||||
} else if (e.keyCode == '39') {
|
|
||||||
this.onRightArrow();
|
|
||||||
} else if (e.keyCode == '38') {
|
|
||||||
this.onUpArrow();
|
|
||||||
} else if (e.keyCode == '40') {
|
|
||||||
this.onDownArrow();
|
|
||||||
} else if (e.keyCode == '13') {
|
|
||||||
this.onEnterKey();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
makeOverlay() {}
|
makeOverlays() {}
|
||||||
bindOverlay() {}
|
bindOverlay() {}
|
||||||
bind_units() {}
|
bindUnits() {}
|
||||||
|
|
||||||
onLeftArrow() {}
|
onLeftArrow() {}
|
||||||
onRightArrow() {}
|
onRightArrow() {}
|
||||||
@ -272,13 +279,6 @@ export default class BaseChart {
|
|||||||
onDownArrow() {}
|
onDownArrow() {}
|
||||||
onEnterKey() {}
|
onEnterKey() {}
|
||||||
|
|
||||||
// ????????????
|
|
||||||
// Update the data here, then do relevant updates
|
|
||||||
// and drawing in child classes by overriding
|
|
||||||
// The Child chart will only know what a particular update means
|
|
||||||
// and what components are affected,
|
|
||||||
// BaseChart shouldn't be doing the animating
|
|
||||||
|
|
||||||
getDataPoint(index = 0) {}
|
getDataPoint(index = 0) {}
|
||||||
setCurrentDataPoint(point) {}
|
setCurrentDataPoint(point) {}
|
||||||
|
|
||||||
|
|||||||
@ -1,130 +0,0 @@
|
|||||||
import { getBarHeightAndYAttr } from '../utils/draw-utils';
|
|
||||||
import { createSVG, makePath, makeGradient, wrapInSVGGroup, FONT_SIZE } from '../utils/draw';
|
|
||||||
import { STD_EASING, UNIT_ANIM_DUR, MARKER_LINE_ANIM_DUR, PATH_ANIM_DUR } from '../utils/animate';
|
|
||||||
|
|
||||||
class AxisChartController {
|
|
||||||
constructor(meta) {
|
|
||||||
// TODO: make configurable passing args
|
|
||||||
this.meta = meta || {};
|
|
||||||
this.setupArgs();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupArgs() {
|
|
||||||
this.consts = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
setup() {}
|
|
||||||
|
|
||||||
refreshMeta(meta) {
|
|
||||||
this.meta = Object.assign((this.meta || {}), meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw() {}
|
|
||||||
animate() {}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class AxisController extends AxisChartController {
|
|
||||||
constructor(meta) {
|
|
||||||
super(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
draw(x, y, color, index) {
|
|
||||||
return createSVG('circle', {
|
|
||||||
style: `fill: ${color}`,
|
|
||||||
'data-point-index': index,
|
|
||||||
cx: x,
|
|
||||||
cy: y,
|
|
||||||
r: this.consts.radius
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
animate(dot, x, yTop) {
|
|
||||||
return [dot, {cx: x, cy: yTop}, UNIT_ANIM_DUR, STD_EASING];
|
|
||||||
// dot.animate({cy: yTop}, UNIT_ANIM_DUR, mina.easein);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class LineChartController extends AxisChartController {
|
|
||||||
constructor(meta) {
|
|
||||||
super(meta);
|
|
||||||
}
|
|
||||||
|
|
||||||
setupArgs() {
|
|
||||||
this.consts = {
|
|
||||||
radius: this.meta.dotSize || 4
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// class BarChart extends AxisChart {
|
|
||||||
// constructor(args) {
|
|
||||||
// super(args);
|
|
||||||
// this.type = 'bar';
|
|
||||||
// this.setup();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// configure(args) {
|
|
||||||
// super.configure(args);
|
|
||||||
// this.config.xAxisMode = args.xAxisMode || 'tick';
|
|
||||||
// this.config.yAxisMode = args.yAxisMode || 'span';
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // =================================
|
|
||||||
|
|
||||||
// makeOverlay() {
|
|
||||||
// // Just make one out of the first element
|
|
||||||
// let index = this.xAxisLabels.length - 1;
|
|
||||||
// let unit = this.y[0].svg_units[index];
|
|
||||||
// this.setCurrentDataPoint(index);
|
|
||||||
|
|
||||||
// if(this.overlay) {
|
|
||||||
// this.overlay.parentNode.removeChild(this.overlay);
|
|
||||||
// }
|
|
||||||
// this.overlay = unit.cloneNode();
|
|
||||||
// this.overlay.style.fill = '#000000';
|
|
||||||
// this.overlay.style.opacity = '0.4';
|
|
||||||
// this.drawArea.appendChild(this.overlay);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bindOverlay() {
|
|
||||||
// // on event, update overlay
|
|
||||||
// this.parent.addEventListener('data-select', (e) => {
|
|
||||||
// this.update_overlay(e.svg_unit);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// bind_units(units_array) {
|
|
||||||
// units_array.map(unit => {
|
|
||||||
// unit.addEventListener('click', () => {
|
|
||||||
// let index = unit.getAttribute('data-point-index');
|
|
||||||
// this.setCurrentDataPoint(index);
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// update_overlay(unit) {
|
|
||||||
// let attributes = [];
|
|
||||||
// Object.keys(unit.attributes).map(index => {
|
|
||||||
// attributes.push(unit.attributes[index]);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// attributes.filter(attr => attr.specified).map(attr => {
|
|
||||||
// this.overlay.setAttribute(attr.name, attr.nodeValue);
|
|
||||||
// });
|
|
||||||
|
|
||||||
// this.overlay.style.fill = '#000000';
|
|
||||||
// this.overlay.style.opacity = '0.4';
|
|
||||||
// }
|
|
||||||
|
|
||||||
// onLeftArrow() {
|
|
||||||
// this.setCurrentDataPoint(this.currentIndex - 1);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// onRightArrow() {
|
|
||||||
// this.setCurrentDataPoint(this.currentIndex + 1);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
@ -58,10 +58,6 @@ class ChartComponent {
|
|||||||
if(animate) {
|
if(animate) {
|
||||||
animateElements = this.animateElements(this.data);
|
animateElements = this.animateElements(this.data);
|
||||||
}
|
}
|
||||||
// TODO: Can we remove this?
|
|
||||||
setTimeout(() => {
|
|
||||||
this.make();
|
|
||||||
}, 1400);
|
|
||||||
return animateElements;
|
return animateElements;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -201,9 +197,10 @@ let componentConfigs = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
barGraph: {
|
barGraph: {
|
||||||
layerClass: function() { return 'dataset-units dataset-' + this.constants.index; },
|
layerClass: function() { return 'dataset-units dataset-bars dataset-' + this.constants.index; },
|
||||||
makeElements(data) {
|
makeElements(data) {
|
||||||
let c = this.constants;
|
let c = this.constants;
|
||||||
|
this.unitType = 'bar';
|
||||||
return data.yPositions.map((y, j) => {
|
return data.yPositions.map((y, j) => {
|
||||||
return datasetBar(
|
return datasetBar(
|
||||||
data.xPositions[j],
|
data.xPositions[j],
|
||||||
@ -269,9 +266,11 @@ let componentConfigs = {
|
|||||||
},
|
},
|
||||||
|
|
||||||
lineGraph: {
|
lineGraph: {
|
||||||
layerClass: function() { return 'dataset-units dataset-' + this.constants.index; },
|
layerClass: function() { return 'dataset-units dataset-line dataset-' + this.constants.index; },
|
||||||
makeElements(data) {
|
makeElements(data) {
|
||||||
let c = this.constants;
|
let c = this.constants;
|
||||||
|
this.unitType = 'dot';
|
||||||
|
|
||||||
this.paths = getPaths(
|
this.paths = getPaths(
|
||||||
data.xPositions,
|
data.xPositions,
|
||||||
data.yPositions,
|
data.yPositions,
|
||||||
@ -302,6 +301,7 @@ let componentConfigs = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Object.values(this.paths).concat(this.dots);
|
return Object.values(this.paths).concat(this.dots);
|
||||||
|
// return this.dots;
|
||||||
},
|
},
|
||||||
animateElements(newData) {
|
animateElements(newData) {
|
||||||
let c = this.constants;
|
let c = this.constants;
|
||||||
|
|||||||
@ -6,4 +6,6 @@ export const AXIS_DATASET_CHART_TYPES = ['line', 'bar'];
|
|||||||
export const BAR_CHART_SPACE_RATIO = 0.5;
|
export const BAR_CHART_SPACE_RATIO = 0.5;
|
||||||
export const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
export const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||||
|
|
||||||
export const LINE_CHART_DOT_SIZE = 4;
|
export const LINE_CHART_DOT_SIZE = 4;
|
||||||
|
|
||||||
|
export const DOT_OVERLAY_SIZE_INCR = 4;
|
||||||
@ -1,6 +1,7 @@
|
|||||||
import { getBarHeightAndYAttr } from './draw-utils';
|
import { getBarHeightAndYAttr } from './draw-utils';
|
||||||
import { getStringWidth } from './helpers';
|
import { getStringWidth } from './helpers';
|
||||||
import { STD_EASING, UNIT_ANIM_DUR, MARKER_LINE_ANIM_DUR, PATH_ANIM_DUR } from './animate';
|
import { STD_EASING, UNIT_ANIM_DUR, MARKER_LINE_ANIM_DUR, PATH_ANIM_DUR } from './animate';
|
||||||
|
import { DOT_OVERLAY_SIZE_INCR } from './constants';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
@ -362,7 +363,6 @@ 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);
|
|
||||||
y -= offset;
|
y -= offset;
|
||||||
|
|
||||||
let rect = createSVG('rect', {
|
let rect = createSVG('rect', {
|
||||||
@ -461,3 +461,78 @@ export function getPaths(xList, yList, color, options={}, meta={}) {
|
|||||||
|
|
||||||
return paths;
|
return paths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export let makeOverlay = {
|
||||||
|
'bar': (unit) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'rect') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let overlay = unit.cloneNode();
|
||||||
|
overlay.style.fill = '#000000';
|
||||||
|
overlay.style.opacity = '0.4';
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
return overlay;
|
||||||
|
},
|
||||||
|
|
||||||
|
'dot': (unit) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'circle') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let overlay = unit.cloneNode();
|
||||||
|
let radius = unit.getAttribute('r');
|
||||||
|
overlay.setAttribute('r', radius + DOT_OVERLAY_SIZE_INCR);
|
||||||
|
overlay.style.fill = '#000000';
|
||||||
|
overlay.style.opacity = '0.4';
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
return overlay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export let updateOverlay = {
|
||||||
|
'bar': (unit, overlay) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'rect') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let attributes = ['x', 'y', 'width', 'height'];
|
||||||
|
Object.values(unit.attributes)
|
||||||
|
.filter(attr => attributes.includes(attr.name) && attr.specified)
|
||||||
|
.map(attr => {
|
||||||
|
overlay.setAttribute(attr.name, attr.nodeValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'dot': (unit, overlay) => {
|
||||||
|
let transformValue;
|
||||||
|
if(unit.nodeName !== 'circle') {
|
||||||
|
transformValue = unit.getAttribute('transform');
|
||||||
|
unit = unit.childNodes[0];
|
||||||
|
}
|
||||||
|
let attributes = ['cx', 'cy'];
|
||||||
|
Object.values(unit.attributes)
|
||||||
|
.filter(attr => attributes.includes(attr.name) && attr.specified)
|
||||||
|
.map(attr => {
|
||||||
|
overlay.setAttribute(attr.name, attr.nodeValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
if(transformValue) {
|
||||||
|
overlay.setAttribute('transform', transformValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user