axis chart renderer
This commit is contained in:
parent
f2616bfa08
commit
02685dab7e
490
dist/frappe-charts.esm.js
vendored
490
dist/frappe-charts.esm.js
vendored
@ -247,62 +247,6 @@ function fillArray(array, count, element, start=false) {
|
|||||||
|
|
||||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
function getXLineProps(totalHeight, mode) {
|
|
||||||
let startAt = totalHeight + 6, height, textStartAt, axisLineClass = '';
|
|
||||||
if(mode === 'span') { // long spanning lines
|
|
||||||
startAt = -7;
|
|
||||||
height = totalHeight + 15;
|
|
||||||
textStartAt = totalHeight + 25;
|
|
||||||
} else if(mode === 'tick'){ // short label lines
|
|
||||||
startAt = totalHeight;
|
|
||||||
height = 6;
|
|
||||||
textStartAt = 9;
|
|
||||||
axisLineClass = 'x-axis-label';
|
|
||||||
}
|
|
||||||
|
|
||||||
return [startAt, height, textStartAt, axisLineClass];
|
|
||||||
}
|
|
||||||
|
|
||||||
// export function getYLineProps(totalWidth, mode, specific=false) {
|
|
||||||
function getYLineProps(totalWidth, mode) {
|
|
||||||
// if(specific) {
|
|
||||||
// return[totalWidth, totalWidth + 5, 'specific-value', 0];
|
|
||||||
// }
|
|
||||||
let width, text_end_at = -9, axisLineClass = '', startAt = 0;
|
|
||||||
if(mode === 'span') { // long spanning lines
|
|
||||||
width = totalWidth + 6;
|
|
||||||
startAt = -6;
|
|
||||||
} else if(mode === 'tick'){ // short label lines
|
|
||||||
width = -6;
|
|
||||||
axisLineClass = 'y-axis-label';
|
|
||||||
}
|
|
||||||
|
|
||||||
return [width, text_end_at, axisLineClass, startAt];
|
|
||||||
}
|
|
||||||
|
|
||||||
// let char_width = 8;
|
|
||||||
// let allowed_space = avg_unit_width * 1.5;
|
|
||||||
// let allowed_letters = allowed_space / 8;
|
|
||||||
|
|
||||||
// return values.map((value, i) => {
|
|
||||||
// let space_taken = getStringWidth(value, char_width) + 2;
|
|
||||||
// if(space_taken > allowed_space) {
|
|
||||||
// if(is_series) {
|
|
||||||
// // Skip some axis lines if X axis is a series
|
|
||||||
// let skips = 1;
|
|
||||||
// while((space_taken/skips)*2 > allowed_space) {
|
|
||||||
// skips++;
|
|
||||||
// }
|
|
||||||
// if(i % skips !== 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// value = value.slice(0, allowed_letters-3) + " ...";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||||
let height, y;
|
let height, y;
|
||||||
if (yTop <= zeroLine) {
|
if (yTop <= zeroLine) {
|
||||||
@ -338,11 +282,30 @@ function equilizeNoOfElements(array1, array2,
|
|||||||
return [array1, array2];
|
return [array1, array2];
|
||||||
}
|
}
|
||||||
|
|
||||||
const X_LABEL_CLASS = 'x-value-text';
|
// let char_width = 8;
|
||||||
const Y_LABEL_CLASS = 'y-value-text';
|
// let allowed_space = avgUnitWidth * 1.5;
|
||||||
|
// let allowed_letters = allowed_space / 8;
|
||||||
|
|
||||||
// const X_AXIS_LINE_CLASS = 'x-value-text';
|
// return values.map((value, i) => {
|
||||||
// const Y_AXIS_LINE_CLASS = 'y-value-text';
|
// let space_taken = getStringWidth(value, char_width) + 2;
|
||||||
|
// if(space_taken > allowed_space) {
|
||||||
|
// if(is_series) {
|
||||||
|
// // Skip some axis lines if X axis is a series
|
||||||
|
// let skips = 1;
|
||||||
|
// while((space_taken/skips)*2 > allowed_space) {
|
||||||
|
// skips++;
|
||||||
|
// }
|
||||||
|
// if(i % skips !== 0) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// value = value.slice(0, allowed_letters-3) + " ...";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
const AXIS_TICK_LENGTH = 6;
|
||||||
|
const LABEL_MARGIN = 4;
|
||||||
|
const FONT_SIZE = 10;
|
||||||
|
|
||||||
function $$1(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;
|
||||||
@ -472,125 +435,136 @@ function makeText(className, x, y, content) {
|
|||||||
className: className,
|
className: className,
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
dy: '.32em',
|
dy: (FONT_SIZE / 2) + 'px',
|
||||||
|
'font-size': FONT_SIZE + 'px',
|
||||||
innerHTML: content
|
innerHTML: content
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var AxisChartRenderer = (function() {
|
function makeVertXLine(x, label, totalHeight, mode) {
|
||||||
var AxisChartRenderer = function(totalHeight, totalWidth, zeroLine, avgUnitWidth, xAxisMode, yAxisMode) {
|
let height = mode === 'span' ? -1 * AXIS_TICK_LENGTH : totalHeight;
|
||||||
this.totalHeight = totalHeight;
|
|
||||||
this.totalWidth = totalWidth;
|
|
||||||
this.zeroLine = zeroLine;
|
|
||||||
this.avgUnitWidth = avgUnitWidth;
|
|
||||||
this.xAxisMode = xAxisMode;
|
|
||||||
this.yAxisMode = yAxisMode;
|
|
||||||
};
|
|
||||||
|
|
||||||
AxisChartRenderer.prototype = {
|
let l = createSVG('line', {
|
||||||
bar: function (x, yTop, args, color, index, datasetIndex, noOfDatasets) {
|
x1: 0,
|
||||||
let totalWidth = this.avgUnitWidth - args.spaceWidth;
|
x2: 0,
|
||||||
let startX = x - totalWidth/2;
|
y1: totalHeight + AXIS_TICK_LENGTH,
|
||||||
|
y2: height
|
||||||
|
});
|
||||||
|
|
||||||
let width = totalWidth / noOfDatasets;
|
let text = createSVG('text', {
|
||||||
let currentX = startX + width * datasetIndex;
|
x: 0,
|
||||||
|
y: totalHeight + AXIS_TICK_LENGTH + LABEL_MARGIN,
|
||||||
|
dy: FONT_SIZE + 'px',
|
||||||
|
'font-size': FONT_SIZE + 'px',
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
innerHTML: label
|
||||||
|
});
|
||||||
|
|
||||||
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
let line = createSVG('g', {
|
||||||
|
transform: `translate(${ x }, 0)`
|
||||||
|
});
|
||||||
|
|
||||||
return createSVG('rect', {
|
line.appendChild(l);
|
||||||
className: `bar mini`,
|
line.appendChild(text);
|
||||||
style: `fill: ${color}`,
|
|
||||||
'data-point-index': index,
|
|
||||||
x: currentX,
|
|
||||||
y: y,
|
|
||||||
width: width,
|
|
||||||
height: height
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
dot: function(x, y, args, color, index) {
|
return line;
|
||||||
return createSVG('circle', {
|
}
|
||||||
style: `fill: ${color}`,
|
|
||||||
'data-point-index': index,
|
|
||||||
cx: x,
|
|
||||||
cy: y,
|
|
||||||
r: args.radius
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
xLine: function(x, label, mode=this.xAxisMode) {
|
function makeHoriYLine(y, label, totalWidth, mode) {
|
||||||
// Draw X axis line in span/tick mode with optional label
|
let lineType = '';
|
||||||
let [startAt, height, textStartAt, axisLineClass] = getXLineProps(this.totalHeight, mode);
|
let width = mode === 'span' ? totalWidth + AXIS_TICK_LENGTH : AXIS_TICK_LENGTH;
|
||||||
let l = createSVG('line', {
|
|
||||||
x1: 0,
|
|
||||||
x2: 0,
|
|
||||||
y1: startAt,
|
|
||||||
y2: height
|
|
||||||
});
|
|
||||||
|
|
||||||
let text = createSVG('text', {
|
let l = createSVG('line', {
|
||||||
className: X_LABEL_CLASS,
|
className: lineType === "dashed" ? "dashed": "",
|
||||||
x: 0,
|
x1: -1 * AXIS_TICK_LENGTH,
|
||||||
y: textStartAt,
|
x2: width,
|
||||||
dy: '.71em',
|
y1: 0,
|
||||||
innerHTML: label
|
y2: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
let line = createSVG('g', {
|
let text = createSVG('text', {
|
||||||
className: `tick ${axisLineClass}`,
|
x: -1 * (LABEL_MARGIN + AXIS_TICK_LENGTH),
|
||||||
transform: `translate(${ x }, 0)`
|
y: 0,
|
||||||
});
|
dy: (FONT_SIZE / 2 - 2) + 'px',
|
||||||
|
'font-size': FONT_SIZE + 'px',
|
||||||
|
'text-anchor': 'end',
|
||||||
|
innerHTML: label+""
|
||||||
|
});
|
||||||
|
|
||||||
line.appendChild(l);
|
let line = createSVG('g', {
|
||||||
line.appendChild(text);
|
transform: `translate(0, ${y})`,
|
||||||
|
'stroke-opacity': 1
|
||||||
|
});
|
||||||
|
|
||||||
return line;
|
if(text === 0 || text === '0') {
|
||||||
},
|
line.style.stroke = "rgba(27, 31, 35, 0.6)";
|
||||||
|
}
|
||||||
|
|
||||||
yLine: function(y, label, mode=this.yAxisMode) {
|
line.appendChild(l);
|
||||||
// TODO: stroke type
|
line.appendChild(text);
|
||||||
let lineType = '';
|
|
||||||
|
|
||||||
let [width, textEndAt, axisLineClass, startAt] = getYLineProps(this.totalWidth, mode);
|
return line;
|
||||||
let l = createSVG('line', {
|
}
|
||||||
className: lineType === "dashed" ? "dashed": "",
|
|
||||||
x1: startAt,
|
|
||||||
x2: width,
|
|
||||||
y1: 0,
|
|
||||||
y2: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
let text = createSVG('text', {
|
class AxisChartRenderer {
|
||||||
className: Y_LABEL_CLASS,
|
constructor(state) {
|
||||||
x: textEndAt,
|
this.updateState(state);
|
||||||
y: 0,
|
}
|
||||||
dy: '.32em',
|
|
||||||
innerHTML: label+""
|
|
||||||
});
|
|
||||||
|
|
||||||
let line = createSVG('g', {
|
updateState(state) {
|
||||||
className: `tick ${axisLineClass}`,
|
this.totalHeight = state.totalHeight;
|
||||||
transform: `translate(0, ${y})`,
|
this.totalWidth = state.totalWidth;
|
||||||
'stroke-opacity': 1
|
this.zeroLine = state.zeroLine;
|
||||||
});
|
this.avgUnitWidth = state.avgUnitWidth;
|
||||||
|
this.xAxisMode = state.xAxisMode;
|
||||||
|
this.yAxisMode = state.yAxisMode;
|
||||||
|
}
|
||||||
|
|
||||||
// if(darker) {
|
bar(x, yTop, args, color, index, datasetIndex, noOfDatasets) {
|
||||||
// line.style.stroke = "rgba(27, 31, 35, 0.6)";
|
let totalWidth = this.avgUnitWidth - args.spaceWidth;
|
||||||
// }
|
let startX = x - totalWidth/2;
|
||||||
|
|
||||||
line.appendChild(l);
|
let width = totalWidth / noOfDatasets;
|
||||||
line.appendChild(text);
|
let currentX = startX + width * datasetIndex;
|
||||||
|
|
||||||
return line;
|
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
||||||
},
|
|
||||||
|
|
||||||
xRegion: function(x1, x2, label) { },
|
return createSVG('rect', {
|
||||||
|
className: `bar mini`,
|
||||||
|
style: `fill: ${color}`,
|
||||||
|
'data-point-index': index,
|
||||||
|
x: currentX,
|
||||||
|
y: y,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
yRegion: function(y1, y2, label) { }
|
dot(x, y, args, color, index) {
|
||||||
};
|
return createSVG('circle', {
|
||||||
|
style: `fill: ${color}`,
|
||||||
|
'data-point-index': index,
|
||||||
|
cx: x,
|
||||||
|
cy: y,
|
||||||
|
r: args.radius
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return AxisChartRenderer;
|
xLine(x, label, mode=this.xAxisMode) {
|
||||||
})();
|
// Draw X axis line in span/tick mode with optional label
|
||||||
|
return makeVertXLine(x, label, this.totalHeight, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
yLine(y, label, mode=this.yAxisMode) {
|
||||||
|
return makeHoriYLine(y, label, this.totalWidth, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xMarker() {}
|
||||||
|
yMarker() {}
|
||||||
|
|
||||||
|
xRegion() {}
|
||||||
|
yRegion() {}
|
||||||
|
}
|
||||||
|
|
||||||
const PRESET_COLOR_MAP = {
|
const PRESET_COLOR_MAP = {
|
||||||
'light-blue': '#7cd6fd',
|
'light-blue': '#7cd6fd',
|
||||||
@ -725,10 +699,12 @@ class BaseChart {
|
|||||||
this.setColors();
|
this.setColors();
|
||||||
this.setMargins();
|
this.setMargins();
|
||||||
|
|
||||||
|
// constants
|
||||||
this.config = {
|
this.config = {
|
||||||
showTooltip: 1,
|
showTooltip: 1,
|
||||||
showLegend: 1,
|
showLegend: 1,
|
||||||
isNavigable: 0
|
isNavigable: 0,
|
||||||
|
animate: 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -770,17 +746,21 @@ class BaseChart {
|
|||||||
|
|
||||||
parseData() {
|
parseData() {
|
||||||
let data = this.rawChartArgs.data;
|
let data = this.rawChartArgs.data;
|
||||||
// Check and all
|
let valid = this.checkData(data);
|
||||||
|
if(!valid) return false;
|
||||||
|
|
||||||
|
|
||||||
// If all good
|
|
||||||
this.data = data;
|
|
||||||
|
|
||||||
|
|
||||||
|
if(!this.config.animate) {
|
||||||
|
this.data = data;
|
||||||
|
} else {
|
||||||
|
[this.data, this.firstUpdateData] =
|
||||||
|
this.getFirstUpdateData(data);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkData() {}
|
||||||
|
getFirstUpdateData(data) {}
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
if(this.validate()) {
|
if(this.validate()) {
|
||||||
this._setup();
|
this._setup();
|
||||||
@ -791,56 +771,19 @@ class BaseChart {
|
|||||||
this.bindWindowEvents();
|
this.bindWindowEvents();
|
||||||
this.setupConstants();
|
this.setupConstants();
|
||||||
|
|
||||||
|
// this.setupComponents();
|
||||||
|
|
||||||
this.makeContainer();
|
this.makeContainer();
|
||||||
this.makeTooltip(); // without binding
|
this.makeTooltip(); // without binding
|
||||||
this.draw(true);
|
this.draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(init=false) {
|
|
||||||
// (draw everything, layers, groups, units)
|
|
||||||
this.calc();
|
|
||||||
this.setupRenderer(); // this chart's rendered with the config
|
|
||||||
this.setupComponents();
|
|
||||||
|
|
||||||
|
|
||||||
this.makeChartArea();
|
|
||||||
this.makeLayers();
|
|
||||||
|
|
||||||
this.renderComponents(); // with zero values
|
|
||||||
this.renderLegend();
|
|
||||||
this.setupNavigation(init);
|
|
||||||
|
|
||||||
if(init) this.update(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bindWindowEvents() {
|
bindWindowEvents() {
|
||||||
window.addEventListener('resize', () => this.draw());
|
window.addEventListener('resize orientationchange', () => this.draw());
|
||||||
window.addEventListener('orientationchange', () => this.draw());
|
|
||||||
}
|
|
||||||
|
|
||||||
calcWidth() {
|
|
||||||
let outerAnnotationsWidth = 0;
|
|
||||||
// let charWidth = 8;
|
|
||||||
// this.specificValues.map(val => {
|
|
||||||
// let strWidth = getStringWidth((val.title + ""), charWidth);
|
|
||||||
// if(strWidth > outerAnnotationsWidth) {
|
|
||||||
// outerAnnotationsWidth = strWidth - 40;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
this.baseWidth = getElementContentWidth(this.parent) - outerAnnotationsWidth;
|
|
||||||
this.width = this.baseWidth - this.translateX * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupConstants() {}
|
setupConstants() {}
|
||||||
|
|
||||||
calc() {
|
|
||||||
this.calcWidth();
|
|
||||||
this.reCalc();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupRenderer() {}
|
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
// Components config
|
// Components config
|
||||||
this.components = [];
|
this.components = [];
|
||||||
@ -863,6 +806,58 @@ class BaseChart {
|
|||||||
this.statsWrapper = this.container.querySelector('.graph-stats-container');
|
this.statsWrapper = this.container.querySelector('.graph-stats-container');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeTooltip() {
|
||||||
|
this.tip = new SvgTip({
|
||||||
|
parent: this.chartWrapper,
|
||||||
|
colors: this.colors
|
||||||
|
});
|
||||||
|
this.bindTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(init=false) {
|
||||||
|
// difference from update(): draw the whole object due to groudbreaking event (init, resize, etc.)
|
||||||
|
// (draw everything, layers, groups, units)
|
||||||
|
this.calc();
|
||||||
|
this.refreshRenderer(); // this chart's rendered with the config
|
||||||
|
this.setupComponents();
|
||||||
|
|
||||||
|
this.makeChartArea();
|
||||||
|
this.makeLayers();
|
||||||
|
|
||||||
|
this.renderComponents(); // with zero values
|
||||||
|
this.renderLegend();
|
||||||
|
this.setupNavigation(init);
|
||||||
|
|
||||||
|
if(this.config.animate) this.update(this.firstUpdateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
// difference from draw(): yes you do rerender everything here as well,
|
||||||
|
// but not things like the chart itself, mosty only at component level
|
||||||
|
this.reCalc();
|
||||||
|
this.reRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshRenderer() {}
|
||||||
|
|
||||||
|
calcWidth() {
|
||||||
|
let outerAnnotationsWidth = 0;
|
||||||
|
// let charWidth = 8;
|
||||||
|
// this.specificValues.map(val => {
|
||||||
|
// let strWidth = getStringWidth((val.title + ""), charWidth);
|
||||||
|
// if(strWidth > outerAnnotationsWidth) {
|
||||||
|
// outerAnnotationsWidth = strWidth - 40;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
this.baseWidth = getElementContentWidth(this.parent) - outerAnnotationsWidth;
|
||||||
|
this.width = this.baseWidth - this.translateX * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
calc() {
|
||||||
|
this.calcWidth();
|
||||||
|
this.reCalc();
|
||||||
|
}
|
||||||
|
|
||||||
makeChartArea() {
|
makeChartArea() {
|
||||||
this.svg = makeSVGContainer(
|
this.svg = makeSVGContainer(
|
||||||
this.chartWrapper,
|
this.chartWrapper,
|
||||||
@ -896,11 +891,6 @@ class BaseChart {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
|
||||||
this.reCalc();
|
|
||||||
this.reRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
reCalc() {
|
reCalc() {
|
||||||
// Will update values(state)
|
// Will update values(state)
|
||||||
// Will recalc specific parts depending on the update
|
// Will recalc specific parts depending on the update
|
||||||
@ -931,13 +921,6 @@ class BaseChart {
|
|||||||
|
|
||||||
calcInitStage() {}
|
calcInitStage() {}
|
||||||
|
|
||||||
makeTooltip() {
|
|
||||||
this.tip = new SvgTip({
|
|
||||||
parent: this.chartWrapper,
|
|
||||||
colors: this.colors
|
|
||||||
});
|
|
||||||
this.bindTooltip();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderLegend() {}
|
renderLegend() {}
|
||||||
|
|
||||||
@ -1391,7 +1374,7 @@ class AxisChart extends BaseChart {
|
|||||||
this.is_series = args.is_series;
|
this.is_series = args.is_series;
|
||||||
this.format_tooltip_y = args.format_tooltip_y;
|
this.format_tooltip_y = args.format_tooltip_y;
|
||||||
this.format_tooltip_x = args.format_tooltip_x;
|
this.format_tooltip_x = args.format_tooltip_x;
|
||||||
this.zero_line = this.height;
|
this.zeroLine = this.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseData() {
|
parseData() {
|
||||||
@ -1457,22 +1440,27 @@ class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this should be inherent in BaseChart
|
// this should be inherent in BaseChart
|
||||||
getRenderer() {
|
refreshRenderer() {
|
||||||
// These args are basically the current state/config 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
|
||||||
return new AxisChartRenderer(this.height, this.width,
|
this.renderer = new AxisChartRenderer({
|
||||||
this.zero_line, this.avg_unit_width, this.xAxisMode, this.yAxisMode);
|
totalHeight: this.height,
|
||||||
|
totalWidth: this.width,
|
||||||
|
zeroLine: this.zeroLine,
|
||||||
|
avgUnitWidth: this.avgUnitWidth,
|
||||||
|
xAxisMode: this.xAxisMode,
|
||||||
|
yAxisMode: this.yAxisMode
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
// Must have access to all current data things
|
// Must have access to all current data things
|
||||||
let self = this;
|
let self = this;
|
||||||
let renderer = this.getRenderer();
|
|
||||||
this.yAxis = {
|
this.yAxis = {
|
||||||
layerClass: 'y axis',
|
layerClass: 'y axis',
|
||||||
layer: undefined,
|
layer: undefined,
|
||||||
make: self.makeYLines,
|
make: self.makeYLines.bind(self),
|
||||||
makeArgs: [renderer, self.yAxisPositions, self.yAxisLabels],
|
makeArgs: [self.yAxisPositions, self.yAxisLabels],
|
||||||
store: [],
|
store: [],
|
||||||
// animate? or update? will come to while implementing
|
// animate? or update? will come to while implementing
|
||||||
animate: self.animateYLines,
|
animate: self.animateYLines,
|
||||||
@ -1481,10 +1469,9 @@ class AxisChart extends BaseChart {
|
|||||||
this.xAxis = {
|
this.xAxis = {
|
||||||
layerClass: 'x axis',
|
layerClass: 'x axis',
|
||||||
layer: undefined,
|
layer: undefined,
|
||||||
make: self.makeXLines,
|
make: self.makeXLines.bind(self),
|
||||||
// TODO: better context of renderer
|
|
||||||
// TODO: will implement series skip with avgUnitWidth and isSeries later
|
// TODO: will implement series skip with avgUnitWidth and isSeries later
|
||||||
makeArgs: [renderer, self.xPositions, self.xAxisLabels],
|
makeArgs: [self.xPositions, self.xAxisLabels],
|
||||||
store: [],
|
store: [],
|
||||||
animate: self.animateXLines
|
animate: self.animateXLines
|
||||||
};
|
};
|
||||||
@ -1535,12 +1522,12 @@ class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setup_x() {
|
setup_x() {
|
||||||
this.set_avg_unit_width_and_x_offset();
|
this.set_avgUnitWidth_and_x_offset();
|
||||||
if(this.xPositions) {
|
if(this.xPositions) {
|
||||||
this.x_old_axis_positions = this.xPositions.slice();
|
this.x_old_axis_positions = this.xPositions.slice();
|
||||||
}
|
}
|
||||||
this.xPositions = this.xAxisLabels.map((d, i) =>
|
this.xPositions = this.xAxisLabels.map((d, i) =>
|
||||||
floatTwo(this.x_offset + i * this.avg_unit_width));
|
floatTwo(this.x_offset + i * this.avgUnitWidth));
|
||||||
|
|
||||||
if(!this.x_old_axis_positions) {
|
if(!this.x_old_axis_positions) {
|
||||||
this.x_old_axis_positions = this.xPositions.slice();
|
this.x_old_axis_positions = this.xPositions.slice();
|
||||||
@ -1592,28 +1579,27 @@ class AxisChart extends BaseChart {
|
|||||||
zero_index = (-1) * max / interval + (y_pts.length - 1);
|
zero_index = (-1) * max / interval + (y_pts.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.zero_line) this.old_zero_line = this.zero_line;
|
if(this.zeroLine) this.old_zeroLine = this.zeroLine;
|
||||||
this.zero_line = this.height - (zero_index * interval_height);
|
this.zeroLine = this.height - (zero_index * interval_height);
|
||||||
if(!this.old_zero_line) this.old_zero_line = this.zero_line;
|
if(!this.old_zeroLine) this.old_zeroLine = this.zeroLine;
|
||||||
|
|
||||||
// Make positions arrays for y elements
|
// Make positions arrays for y elements
|
||||||
if(this.yAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
if(this.yAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
||||||
this.yAxisPositions = this.yAxisLabels.map(d => this.zero_line - d * this.multiplier);
|
this.yAxisPositions = this.yAxisLabels.map(d => this.zeroLine - d * this.multiplier);
|
||||||
if(!this.oldYAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
if(!this.oldYAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
||||||
|
|
||||||
// if(this.yAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
// if(this.yAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
||||||
// this.yAnnotationPositions = this.specific_values.map(d => this.zero_line - d.value * this.multiplier);
|
// this.yAnnotationPositions = this.specific_values.map(d => this.zeroLine - d.value * this.multiplier);
|
||||||
// if(!this.oldYAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
// if(!this.oldYAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeXLines(renderer, positions, values) {
|
makeXLines(positions, values) {
|
||||||
// TODO: draw as per condition
|
// TODO: draw as per condition (with/without label etc.)
|
||||||
|
return positions.map((position, i) => this.renderer.xLine(position, values[i]));
|
||||||
return positions.map((position, i) => renderer.xLine(position, values[i]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
makeYLines(renderer, positions, values) {
|
makeYLines(positions, values) {
|
||||||
return positions.map((position, i) => renderer.yLine(position, values[i]));
|
return positions.map((position, i) => this.renderer.yLine(position, values[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_graph(init=false) {
|
draw_graph(init=false) {
|
||||||
@ -1642,7 +1628,7 @@ class AxisChart extends BaseChart {
|
|||||||
let data = [];
|
let data = [];
|
||||||
this.y.map((d, i) => {
|
this.y.map((d, i) => {
|
||||||
// Anim: Don't draw initial values, store them and update later
|
// Anim: Don't draw initial values, store them and update later
|
||||||
d.yUnitPositions = new Array(d.values.length).fill(this.zero_line); // no value
|
d.yUnitPositions = new Array(d.values.length).fill(this.zeroLine); // no value
|
||||||
data.push({values: d.values});
|
data.push({values: d.values});
|
||||||
d.svg_units = [];
|
d.svg_units = [];
|
||||||
|
|
||||||
@ -1686,7 +1672,7 @@ class AxisChart extends BaseChart {
|
|||||||
units_group.textContent = '';
|
units_group.textContent = '';
|
||||||
units_array.length = 0;
|
units_array.length = 0;
|
||||||
|
|
||||||
let unit_AxisChartRenderer = new AxisChartRenderer(this.height, this.zero_line, this.avg_unit_width);
|
let unit_AxisChartRenderer = new AxisChartRenderer(this.height, this.zeroLine, this.avgUnitWidth);
|
||||||
|
|
||||||
y_values.map((y, i) => {
|
y_values.map((y, i) => {
|
||||||
let data_unit = unit_AxisChartRenderer[unit.type](
|
let data_unit = unit_AxisChartRenderer[unit.type](
|
||||||
@ -1734,8 +1720,8 @@ class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
for(var i=this.xPositions.length - 1; i >= 0 ; i--) {
|
for(var i=this.xPositions.length - 1; i >= 0 ; i--) {
|
||||||
let x_val = this.xPositions[i];
|
let x_val = this.xPositions[i];
|
||||||
// let delta = i === 0 ? this.avg_unit_width : x_val - this.xPositions[i-1];
|
// let delta = i === 0 ? this.avgUnitWidth : x_val - this.xPositions[i-1];
|
||||||
if(relX > x_val - this.avg_unit_width/2) {
|
if(relX > x_val - this.avgUnitWidth/2) {
|
||||||
let x = x_val + this.translateX;
|
let x = x_val + this.translateX;
|
||||||
let y = this.y_min_tops[i] + this.translateY;
|
let y = this.y_min_tops[i] + this.translateY;
|
||||||
|
|
||||||
@ -1778,7 +1764,7 @@ class AxisChart extends BaseChart {
|
|||||||
this.calcYDependencies();
|
this.calcYDependencies();
|
||||||
|
|
||||||
// Got the values? Now begin drawing
|
// Got the values? Now begin drawing
|
||||||
this.animator = new Animator(this.height, this.width, this.zero_line, this.avg_unit_width);
|
this.animator = new Animator(this.height, this.width, this.zeroLine, this.avgUnitWidth);
|
||||||
|
|
||||||
this.animate_graphs();
|
this.animate_graphs();
|
||||||
|
|
||||||
@ -1927,9 +1913,9 @@ class AxisChart extends BaseChart {
|
|||||||
fire(this.parent, "data-select", this.getDataPoint());
|
fire(this.parent, "data-select", this.getDataPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
set_avg_unit_width_and_x_offset() {
|
set_avgUnitWidth_and_x_offset() {
|
||||||
// Set the ... you get it
|
// Set the ... you get it
|
||||||
this.avg_unit_width = this.width/(this.xAxisLabels.length - 1);
|
this.avgUnitWidth = this.width/(this.xAxisLabels.length - 1);
|
||||||
this.x_offset = 0;
|
this.x_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1948,7 +1934,7 @@ class AxisChart extends BaseChart {
|
|||||||
calcYDependencies() {
|
calcYDependencies() {
|
||||||
this.y_min_tops = new Array(this.xAxisLabels.length).fill(9999);
|
this.y_min_tops = new Array(this.xAxisLabels.length).fill(9999);
|
||||||
this.y.map(d => {
|
this.y.map(d => {
|
||||||
d.yUnitPositions = d.values.map( val => floatTwo(this.zero_line - val * this.multiplier));
|
d.yUnitPositions = d.values.map( val => floatTwo(this.zeroLine - val * this.multiplier));
|
||||||
d.yUnitPositions.map( (yUnitPosition, i) => {
|
d.yUnitPositions.map( (yUnitPosition, i) => {
|
||||||
if(yUnitPosition < this.y_min_tops[i]) {
|
if(yUnitPosition < this.y_min_tops[i]) {
|
||||||
this.y_min_tops[i] = yUnitPosition;
|
this.y_min_tops[i] = yUnitPosition;
|
||||||
@ -1972,11 +1958,11 @@ class BarChart extends AxisChart {
|
|||||||
|
|
||||||
setup_values() {
|
setup_values() {
|
||||||
super.setup_values();
|
super.setup_values();
|
||||||
this.x_offset = this.avg_unit_width;
|
this.x_offset = this.avgUnitWidth;
|
||||||
this.unit_args = {
|
this.unit_args = {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
args: {
|
args: {
|
||||||
spaceWidth: this.avg_unit_width/2,
|
spaceWidth: this.avgUnitWidth/2,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2034,9 +2020,9 @@ class BarChart extends AxisChart {
|
|||||||
this.updateCurrentDataPoint(this.currentIndex + 1);
|
this.updateCurrentDataPoint(this.currentIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_avg_unit_width_and_x_offset() {
|
set_avgUnitWidth_and_x_offset() {
|
||||||
this.avg_unit_width = this.width/(this.xAxisLabels.length + 1);
|
this.avgUnitWidth = this.width/(this.xAxisLabels.length + 1);
|
||||||
this.x_offset = this.avg_unit_width;
|
this.x_offset = this.avgUnitWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2118,7 +2104,7 @@ class LineChart extends AxisChart {
|
|||||||
|
|
||||||
fill_region_for_dataset(d, color, points_str) {
|
fill_region_for_dataset(d, color, points_str) {
|
||||||
let gradient_id = makeGradient(this.svg_defs, color, true);
|
let gradient_id = makeGradient(this.svg_defs, color, true);
|
||||||
let pathStr = "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`;
|
let pathStr = "M" + `0,${this.zeroLine}L` + points_str + `L${this.width},${this.zeroLine}`;
|
||||||
|
|
||||||
d.regionPath = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
d.regionPath = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
||||||
this.paths_groups[d.index].appendChild(d.regionPath);
|
this.paths_groups[d.index].appendChild(d.regionPath);
|
||||||
|
|||||||
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.css
vendored
2
dist/frappe-charts.min.css
vendored
@ -1 +1 @@
|
|||||||
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .graph-focus-margin{margin:0 5%}.chart-container>.title{margin-top:25px;margin-left:25px;text-align:left;font-weight:400;font-size:12px;color:#6c7680}.chart-container .graphics{margin-top:10px;padding-top:10px;padding-bottom:10px;position:relative}.chart-container .graph-stats-group{-ms-flex-pack:distribute;-webkit-box-flex:1;-ms-flex:1;flex:1}.chart-container .graph-stats-container,.chart-container .graph-stats-group{display:-webkit-box;display:-ms-flexbox;display:flex;justify-content:space-around}.chart-container .graph-stats-container{-ms-flex-pack:distribute;padding-top:10px}.chart-container .graph-stats-container .stats{padding-bottom:15px}.chart-container .graph-stats-container .stats-title{color:#8d99a6}.chart-container .graph-stats-container .stats-value{font-size:20px;font-weight:300}.chart-container .graph-stats-container .stats-description{font-size:12px;color:#8d99a6}.chart-container .graph-stats-container .graph-data .stats-value{color:#98d85b}.chart-container .axis,.chart-container .chart-label{font-size:11px;fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .percentage-graph .progress{margin-bottom:0}.chart-container .data-points circle{stroke:#fff;stroke-width:2}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .tick.x-axis-label{display:block}.chart-container .tick .specific-value{text-anchor:start}.chart-container .tick .y-value-text{text-anchor:end}.chart-container .tick .x-value-text{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}.chart-container .indicator,.chart-container .indicator-right{background:none;font-size:12px;vertical-align:middle;font-weight:700;color:#6c7680}.chart-container .indicator i{content:"";display:inline-block;height:8px;width:8px;border-radius:8px}.chart-container .indicator:before,.chart-container .indicator i{margin:0 4px 0 0}.chart-container .indicator-right:after{margin:0 0 0 4px}
|
.chart-container{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif}.chart-container .graph-focus-margin{margin:0 5%}.chart-container>.title{margin-top:25px;margin-left:25px;text-align:left;font-weight:400;font-size:12px;color:#6c7680}.chart-container .graphics{margin-top:10px;padding-top:10px;padding-bottom:10px;position:relative}.chart-container .graph-stats-group{-ms-flex-pack:distribute;-webkit-box-flex:1;-ms-flex:1;flex:1}.chart-container .graph-stats-container,.chart-container .graph-stats-group{display:-webkit-box;display:-ms-flexbox;display:flex;justify-content:space-around}.chart-container .graph-stats-container{-ms-flex-pack:distribute;padding-top:10px}.chart-container .graph-stats-container .stats{padding-bottom:15px}.chart-container .graph-stats-container .stats-title{color:#8d99a6}.chart-container .graph-stats-container .stats-value{font-size:20px;font-weight:300}.chart-container .graph-stats-container .stats-description{font-size:12px;color:#8d99a6}.chart-container .graph-stats-container .graph-data .stats-value{color:#98d85b}.chart-container .axis,.chart-container .chart-label{fill:#555b51}.chart-container .axis line,.chart-container .chart-label line{stroke:#dadada}.chart-container .percentage-graph .progress{margin-bottom:0}.chart-container .data-points circle{stroke:#fff;stroke-width:2}.chart-container .path-group path{fill:none;stroke-opacity:1;stroke-width:2px}.chart-container line.dashed{stroke-dasharray:5,3}.chart-container .axis-line .specific-value{text-anchor:start}.chart-container .axis-line .y-line{text-anchor:end}.chart-container .axis-line .x-line{text-anchor:middle}.chart-container .progress{height:20px;margin-bottom:20px;overflow:hidden;background-color:#f5f5f5;border-radius:4px;-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,.1);box-shadow:inset 0 1px 2px rgba(0,0,0,.1)}.chart-container .progress-bar{float:left;width:0;height:100%;font-size:12px;line-height:20px;color:#fff;text-align:center;background-color:#36414c;-webkit-box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);box-shadow:inset 0 -1px 0 rgba(0,0,0,.15);-webkit-transition:width .6s ease;transition:width .6s ease}.chart-container .graph-svg-tip{position:absolute;z-index:1;padding:10px;font-size:12px;color:#959da5;text-align:center;background:rgba(0,0,0,.8);border-radius:3px}.chart-container .graph-svg-tip ol,.chart-container .graph-svg-tip ul{padding-left:0;display:-webkit-box;display:-ms-flexbox;display:flex}.chart-container .graph-svg-tip ul.data-point-list li{min-width:90px;-webkit-box-flex:1;-ms-flex:1;flex:1;font-weight:600}.chart-container .graph-svg-tip strong{color:#dfe2e5;font-weight:600}.chart-container .graph-svg-tip .svg-pointer{position:absolute;height:5px;margin:0 0 0 -5px;content:" ";border:5px solid transparent;border-top-color:rgba(0,0,0,.8)}.chart-container .graph-svg-tip.comparison{padding:0;text-align:left;pointer-events:none}.chart-container .graph-svg-tip.comparison .title{display:block;padding:10px;margin:0;font-weight:600;line-height:1;pointer-events:none}.chart-container .graph-svg-tip.comparison ul{margin:0;white-space:nowrap;list-style:none}.chart-container .graph-svg-tip.comparison li{display:inline-block;padding:5px 10px}.chart-container .indicator,.chart-container .indicator-right{background:none;font-size:12px;vertical-align:middle;font-weight:700;color:#6c7680}.chart-container .indicator i{content:"";display:inline-block;height:8px;width:8px;border-radius:8px}.chart-container .indicator:before,.chart-container .indicator i{margin:0 4px 0 0}.chart-container .indicator-right:after{margin:0 0 0 4px}
|
||||||
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
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
@ -13,7 +13,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
this.is_series = args.is_series;
|
this.is_series = args.is_series;
|
||||||
this.format_tooltip_y = args.format_tooltip_y;
|
this.format_tooltip_y = args.format_tooltip_y;
|
||||||
this.format_tooltip_x = args.format_tooltip_x;
|
this.format_tooltip_x = args.format_tooltip_x;
|
||||||
this.zero_line = this.height;
|
this.zeroLine = this.height;
|
||||||
}
|
}
|
||||||
|
|
||||||
parseData() {
|
parseData() {
|
||||||
@ -79,22 +79,27 @@ export default class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// this should be inherent in BaseChart
|
// this should be inherent in BaseChart
|
||||||
getRenderer() {
|
refreshRenderer() {
|
||||||
// These args are basically the current state/config 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
|
||||||
return new AxisChartRenderer(this.height, this.width,
|
this.renderer = new AxisChartRenderer({
|
||||||
this.zero_line, this.avg_unit_width, this.xAxisMode, this.yAxisMode);
|
totalHeight: this.height,
|
||||||
|
totalWidth: this.width,
|
||||||
|
zeroLine: this.zeroLine,
|
||||||
|
avgUnitWidth: this.avgUnitWidth,
|
||||||
|
xAxisMode: this.xAxisMode,
|
||||||
|
yAxisMode: this.yAxisMode
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
// Must have access to all current data things
|
// Must have access to all current data things
|
||||||
let self = this;
|
let self = this;
|
||||||
let renderer = this.getRenderer();
|
|
||||||
this.yAxis = {
|
this.yAxis = {
|
||||||
layerClass: 'y axis',
|
layerClass: 'y axis',
|
||||||
layer: undefined,
|
layer: undefined,
|
||||||
make: self.makeYLines,
|
make: self.makeYLines.bind(self),
|
||||||
makeArgs: [renderer, self.yAxisPositions, self.yAxisLabels],
|
makeArgs: [self.yAxisPositions, self.yAxisLabels],
|
||||||
store: [],
|
store: [],
|
||||||
// animate? or update? will come to while implementing
|
// animate? or update? will come to while implementing
|
||||||
animate: self.animateYLines,
|
animate: self.animateYLines,
|
||||||
@ -103,10 +108,9 @@ export default class AxisChart extends BaseChart {
|
|||||||
this.xAxis = {
|
this.xAxis = {
|
||||||
layerClass: 'x axis',
|
layerClass: 'x axis',
|
||||||
layer: undefined,
|
layer: undefined,
|
||||||
make: self.makeXLines,
|
make: self.makeXLines.bind(self),
|
||||||
// TODO: better context of renderer
|
|
||||||
// TODO: will implement series skip with avgUnitWidth and isSeries later
|
// TODO: will implement series skip with avgUnitWidth and isSeries later
|
||||||
makeArgs: [renderer, self.xPositions, self.xAxisLabels],
|
makeArgs: [self.xPositions, self.xAxisLabels],
|
||||||
store: [],
|
store: [],
|
||||||
animate: self.animateXLines
|
animate: self.animateXLines
|
||||||
};
|
};
|
||||||
@ -157,12 +161,12 @@ export default class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setup_x() {
|
setup_x() {
|
||||||
this.set_avg_unit_width_and_x_offset();
|
this.set_avgUnitWidth_and_x_offset();
|
||||||
if(this.xPositions) {
|
if(this.xPositions) {
|
||||||
this.x_old_axis_positions = this.xPositions.slice();
|
this.x_old_axis_positions = this.xPositions.slice();
|
||||||
}
|
}
|
||||||
this.xPositions = this.xAxisLabels.map((d, i) =>
|
this.xPositions = this.xAxisLabels.map((d, i) =>
|
||||||
floatTwo(this.x_offset + i * this.avg_unit_width));
|
floatTwo(this.x_offset + i * this.avgUnitWidth));
|
||||||
|
|
||||||
if(!this.x_old_axis_positions) {
|
if(!this.x_old_axis_positions) {
|
||||||
this.x_old_axis_positions = this.xPositions.slice();
|
this.x_old_axis_positions = this.xPositions.slice();
|
||||||
@ -214,28 +218,27 @@ export default class AxisChart extends BaseChart {
|
|||||||
zero_index = (-1) * max / interval + (y_pts.length - 1);
|
zero_index = (-1) * max / interval + (y_pts.length - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(this.zero_line) this.old_zero_line = this.zero_line;
|
if(this.zeroLine) this.old_zeroLine = this.zeroLine;
|
||||||
this.zero_line = this.height - (zero_index * interval_height);
|
this.zeroLine = this.height - (zero_index * interval_height);
|
||||||
if(!this.old_zero_line) this.old_zero_line = this.zero_line;
|
if(!this.old_zeroLine) this.old_zeroLine = this.zeroLine;
|
||||||
|
|
||||||
// Make positions arrays for y elements
|
// Make positions arrays for y elements
|
||||||
if(this.yAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
if(this.yAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
||||||
this.yAxisPositions = this.yAxisLabels.map(d => this.zero_line - d * this.multiplier);
|
this.yAxisPositions = this.yAxisLabels.map(d => this.zeroLine - d * this.multiplier);
|
||||||
if(!this.oldYAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
if(!this.oldYAxisPositions) this.oldYAxisPositions = this.yAxisPositions;
|
||||||
|
|
||||||
// if(this.yAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
// if(this.yAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
||||||
// this.yAnnotationPositions = this.specific_values.map(d => this.zero_line - d.value * this.multiplier);
|
// this.yAnnotationPositions = this.specific_values.map(d => this.zeroLine - d.value * this.multiplier);
|
||||||
// if(!this.oldYAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
// if(!this.oldYAnnotationPositions) this.oldYAnnotationPositions = this.yAnnotationPositions;
|
||||||
}
|
}
|
||||||
|
|
||||||
makeXLines(renderer, positions, values) {
|
makeXLines(positions, values) {
|
||||||
// TODO: draw as per condition
|
// TODO: draw as per condition (with/without label etc.)
|
||||||
|
return positions.map((position, i) => this.renderer.xLine(position, values[i]));
|
||||||
return positions.map((position, i) => renderer.xLine(position, values[i]));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
makeYLines(renderer, positions, values) {
|
makeYLines(positions, values) {
|
||||||
return positions.map((position, i) => renderer.yLine(position, values[i]));
|
return positions.map((position, i) => this.renderer.yLine(position, values[i]));
|
||||||
}
|
}
|
||||||
|
|
||||||
draw_graph(init=false) {
|
draw_graph(init=false) {
|
||||||
@ -264,7 +267,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
let data = [];
|
let data = [];
|
||||||
this.y.map((d, i) => {
|
this.y.map((d, i) => {
|
||||||
// Anim: Don't draw initial values, store them and update later
|
// Anim: Don't draw initial values, store them and update later
|
||||||
d.yUnitPositions = new Array(d.values.length).fill(this.zero_line); // no value
|
d.yUnitPositions = new Array(d.values.length).fill(this.zeroLine); // no value
|
||||||
data.push({values: d.values});
|
data.push({values: d.values});
|
||||||
d.svg_units = [];
|
d.svg_units = [];
|
||||||
|
|
||||||
@ -308,7 +311,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
units_group.textContent = '';
|
units_group.textContent = '';
|
||||||
units_array.length = 0;
|
units_array.length = 0;
|
||||||
|
|
||||||
let unit_AxisChartRenderer = new AxisChartRenderer(this.height, this.zero_line, this.avg_unit_width);
|
let unit_AxisChartRenderer = new AxisChartRenderer(this.height, this.zeroLine, this.avgUnitWidth);
|
||||||
|
|
||||||
y_values.map((y, i) => {
|
y_values.map((y, i) => {
|
||||||
let data_unit = unit_AxisChartRenderer[unit.type](
|
let data_unit = unit_AxisChartRenderer[unit.type](
|
||||||
@ -356,8 +359,8 @@ export default class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
for(var i=this.xPositions.length - 1; i >= 0 ; i--) {
|
for(var i=this.xPositions.length - 1; i >= 0 ; i--) {
|
||||||
let x_val = this.xPositions[i];
|
let x_val = this.xPositions[i];
|
||||||
// let delta = i === 0 ? this.avg_unit_width : x_val - this.xPositions[i-1];
|
// let delta = i === 0 ? this.avgUnitWidth : x_val - this.xPositions[i-1];
|
||||||
if(relX > x_val - this.avg_unit_width/2) {
|
if(relX > x_val - this.avgUnitWidth/2) {
|
||||||
let x = x_val + this.translateX;
|
let x = x_val + this.translateX;
|
||||||
let y = this.y_min_tops[i] + this.translateY;
|
let y = this.y_min_tops[i] + this.translateY;
|
||||||
|
|
||||||
@ -400,7 +403,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
this.calcYDependencies();
|
this.calcYDependencies();
|
||||||
|
|
||||||
// Got the values? Now begin drawing
|
// Got the values? Now begin drawing
|
||||||
this.animator = new Animator(this.height, this.width, this.zero_line, this.avg_unit_width);
|
this.animator = new Animator(this.height, this.width, this.zeroLine, this.avgUnitWidth);
|
||||||
|
|
||||||
this.animate_graphs();
|
this.animate_graphs();
|
||||||
|
|
||||||
@ -549,9 +552,9 @@ export default class AxisChart extends BaseChart {
|
|||||||
fire(this.parent, "data-select", this.getDataPoint());
|
fire(this.parent, "data-select", this.getDataPoint());
|
||||||
}
|
}
|
||||||
|
|
||||||
set_avg_unit_width_and_x_offset() {
|
set_avgUnitWidth_and_x_offset() {
|
||||||
// Set the ... you get it
|
// Set the ... you get it
|
||||||
this.avg_unit_width = this.width/(this.xAxisLabels.length - 1);
|
this.avgUnitWidth = this.width/(this.xAxisLabels.length - 1);
|
||||||
this.x_offset = 0;
|
this.x_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -570,7 +573,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
calcYDependencies() {
|
calcYDependencies() {
|
||||||
this.y_min_tops = new Array(this.xAxisLabels.length).fill(9999);
|
this.y_min_tops = new Array(this.xAxisLabels.length).fill(9999);
|
||||||
this.y.map(d => {
|
this.y.map(d => {
|
||||||
d.yUnitPositions = d.values.map( val => floatTwo(this.zero_line - val * this.multiplier));
|
d.yUnitPositions = d.values.map( val => floatTwo(this.zeroLine - val * this.multiplier));
|
||||||
d.yUnitPositions.map( (yUnitPosition, i) => {
|
d.yUnitPositions.map( (yUnitPosition, i) => {
|
||||||
if(yUnitPosition < this.y_min_tops[i]) {
|
if(yUnitPosition < this.y_min_tops[i]) {
|
||||||
this.y_min_tops[i] = yUnitPosition;
|
this.y_min_tops[i] = yUnitPosition;
|
||||||
|
|||||||
@ -12,11 +12,11 @@ export default class BarChart extends AxisChart {
|
|||||||
|
|
||||||
setup_values() {
|
setup_values() {
|
||||||
super.setup_values();
|
super.setup_values();
|
||||||
this.x_offset = this.avg_unit_width;
|
this.x_offset = this.avgUnitWidth;
|
||||||
this.unit_args = {
|
this.unit_args = {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
args: {
|
args: {
|
||||||
spaceWidth: this.avg_unit_width/2,
|
spaceWidth: this.avgUnitWidth/2,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -74,8 +74,8 @@ export default class BarChart extends AxisChart {
|
|||||||
this.updateCurrentDataPoint(this.currentIndex + 1);
|
this.updateCurrentDataPoint(this.currentIndex + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
set_avg_unit_width_and_x_offset() {
|
set_avgUnitWidth_and_x_offset() {
|
||||||
this.avg_unit_width = this.width/(this.xAxisLabels.length + 1);
|
this.avgUnitWidth = this.width/(this.xAxisLabels.length + 1);
|
||||||
this.x_offset = this.avg_unit_width;
|
this.x_offset = this.avgUnitWidth;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,10 +41,12 @@ export default class BaseChart {
|
|||||||
this.setColors();
|
this.setColors();
|
||||||
this.setMargins();
|
this.setMargins();
|
||||||
|
|
||||||
|
// constants
|
||||||
this.config = {
|
this.config = {
|
||||||
showTooltip: 1,
|
showTooltip: 1,
|
||||||
showLegend: 1,
|
showLegend: 1,
|
||||||
isNavigable: 0
|
isNavigable: 0,
|
||||||
|
animate: 1
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,17 +90,21 @@ export default class BaseChart {
|
|||||||
|
|
||||||
parseData() {
|
parseData() {
|
||||||
let data = this.rawChartArgs.data;
|
let data = this.rawChartArgs.data;
|
||||||
// Check and all
|
let valid = this.checkData(data);
|
||||||
|
if(!valid) return false;
|
||||||
|
|
||||||
|
|
||||||
// If all good
|
|
||||||
this.data = data;
|
|
||||||
|
|
||||||
|
|
||||||
|
if(!this.config.animate) {
|
||||||
|
this.data = data;
|
||||||
|
} else {
|
||||||
|
[this.data, this.firstUpdateData] =
|
||||||
|
this.getFirstUpdateData(data);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkData() {}
|
||||||
|
getFirstUpdateData(data) {}
|
||||||
|
|
||||||
setup() {
|
setup() {
|
||||||
if(this.validate()) {
|
if(this.validate()) {
|
||||||
this._setup();
|
this._setup();
|
||||||
@ -109,56 +115,19 @@ export default class BaseChart {
|
|||||||
this.bindWindowEvents();
|
this.bindWindowEvents();
|
||||||
this.setupConstants();
|
this.setupConstants();
|
||||||
|
|
||||||
|
// this.setupComponents();
|
||||||
|
|
||||||
this.makeContainer();
|
this.makeContainer();
|
||||||
this.makeTooltip(); // without binding
|
this.makeTooltip(); // without binding
|
||||||
this.draw(true);
|
this.draw(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
draw(init=false) {
|
|
||||||
// (draw everything, layers, groups, units)
|
|
||||||
this.calc();
|
|
||||||
this.setupRenderer(); // this chart's rendered with the config
|
|
||||||
this.setupComponents();
|
|
||||||
|
|
||||||
|
|
||||||
this.makeChartArea();
|
|
||||||
this.makeLayers();
|
|
||||||
|
|
||||||
this.renderComponents(); // with zero values
|
|
||||||
this.renderLegend();
|
|
||||||
this.setupNavigation(init);
|
|
||||||
|
|
||||||
if(init) this.update(this.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
bindWindowEvents() {
|
bindWindowEvents() {
|
||||||
window.addEventListener('resize', () => this.draw());
|
window.addEventListener('resize orientationchange', () => this.draw());
|
||||||
window.addEventListener('orientationchange', () => this.draw());
|
|
||||||
}
|
|
||||||
|
|
||||||
calcWidth() {
|
|
||||||
let outerAnnotationsWidth = 0;
|
|
||||||
// let charWidth = 8;
|
|
||||||
// this.specificValues.map(val => {
|
|
||||||
// let strWidth = getStringWidth((val.title + ""), charWidth);
|
|
||||||
// if(strWidth > outerAnnotationsWidth) {
|
|
||||||
// outerAnnotationsWidth = strWidth - 40;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
this.baseWidth = getElementContentWidth(this.parent) - outerAnnotationsWidth;
|
|
||||||
this.width = this.baseWidth - this.translateX * 2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setupConstants() {}
|
setupConstants() {}
|
||||||
|
|
||||||
calc() {
|
|
||||||
this.calcWidth();
|
|
||||||
this.reCalc();
|
|
||||||
}
|
|
||||||
|
|
||||||
setupRenderer() {}
|
|
||||||
|
|
||||||
setupComponents() {
|
setupComponents() {
|
||||||
// Components config
|
// Components config
|
||||||
this.components = [];
|
this.components = [];
|
||||||
@ -181,6 +150,58 @@ export default class BaseChart {
|
|||||||
this.statsWrapper = this.container.querySelector('.graph-stats-container');
|
this.statsWrapper = this.container.querySelector('.graph-stats-container');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
makeTooltip() {
|
||||||
|
this.tip = new SvgTip({
|
||||||
|
parent: this.chartWrapper,
|
||||||
|
colors: this.colors
|
||||||
|
});
|
||||||
|
this.bindTooltip();
|
||||||
|
}
|
||||||
|
|
||||||
|
draw(init=false) {
|
||||||
|
// difference from update(): draw the whole object due to groudbreaking event (init, resize, etc.)
|
||||||
|
// (draw everything, layers, groups, units)
|
||||||
|
this.calc();
|
||||||
|
this.refreshRenderer() // this chart's rendered with the config
|
||||||
|
this.setupComponents();
|
||||||
|
|
||||||
|
this.makeChartArea();
|
||||||
|
this.makeLayers();
|
||||||
|
|
||||||
|
this.renderComponents(); // with zero values
|
||||||
|
this.renderLegend();
|
||||||
|
this.setupNavigation(init);
|
||||||
|
|
||||||
|
if(this.config.animate) this.update(this.firstUpdateData);
|
||||||
|
}
|
||||||
|
|
||||||
|
update() {
|
||||||
|
// difference from draw(): yes you do rerender everything here as well,
|
||||||
|
// but not things like the chart itself, mosty only at component level
|
||||||
|
this.reCalc();
|
||||||
|
this.reRender();
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshRenderer() {}
|
||||||
|
|
||||||
|
calcWidth() {
|
||||||
|
let outerAnnotationsWidth = 0;
|
||||||
|
// let charWidth = 8;
|
||||||
|
// this.specificValues.map(val => {
|
||||||
|
// let strWidth = getStringWidth((val.title + ""), charWidth);
|
||||||
|
// if(strWidth > outerAnnotationsWidth) {
|
||||||
|
// outerAnnotationsWidth = strWidth - 40;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
this.baseWidth = getElementContentWidth(this.parent) - outerAnnotationsWidth;
|
||||||
|
this.width = this.baseWidth - this.translateX * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
calc() {
|
||||||
|
this.calcWidth();
|
||||||
|
this.reCalc();
|
||||||
|
}
|
||||||
|
|
||||||
makeChartArea() {
|
makeChartArea() {
|
||||||
this.svg = makeSVGContainer(
|
this.svg = makeSVGContainer(
|
||||||
this.chartWrapper,
|
this.chartWrapper,
|
||||||
@ -214,11 +235,6 @@ export default class BaseChart {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
update() {
|
|
||||||
this.reCalc();
|
|
||||||
this.reRender();
|
|
||||||
}
|
|
||||||
|
|
||||||
reCalc() {
|
reCalc() {
|
||||||
// Will update values(state)
|
// Will update values(state)
|
||||||
// Will recalc specific parts depending on the update
|
// Will recalc specific parts depending on the update
|
||||||
@ -249,13 +265,6 @@ export default class BaseChart {
|
|||||||
|
|
||||||
calcInitStage() {}
|
calcInitStage() {}
|
||||||
|
|
||||||
makeTooltip() {
|
|
||||||
this.tip = new SvgTip({
|
|
||||||
parent: this.chartWrapper,
|
|
||||||
colors: this.colors
|
|
||||||
});
|
|
||||||
this.bindTooltip();
|
|
||||||
}
|
|
||||||
|
|
||||||
renderLegend() {}
|
renderLegend() {}
|
||||||
|
|
||||||
|
|||||||
@ -79,7 +79,7 @@ export default class LineChart extends AxisChart {
|
|||||||
|
|
||||||
fill_region_for_dataset(d, color, points_str) {
|
fill_region_for_dataset(d, color, points_str) {
|
||||||
let gradient_id = makeGradient(this.svg_defs, color, true);
|
let gradient_id = makeGradient(this.svg_defs, color, true);
|
||||||
let pathStr = "M" + `0,${this.zero_line}L` + points_str + `L${this.width},${this.zero_line}`;
|
let pathStr = "M" + `0,${this.zeroLine}L` + points_str + `L${this.width},${this.zeroLine}`;
|
||||||
|
|
||||||
d.regionPath = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
d.regionPath = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
||||||
this.paths_groups[d.index].appendChild(d.regionPath);
|
this.paths_groups[d.index].appendChild(d.regionPath);
|
||||||
|
|||||||
2
src/js/renderers/AxisChartRenderer.js
Normal file
2
src/js/renderers/AxisChartRenderer.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import { getBarHeightAndYAttr } from '../utils/draw-utils';
|
||||||
|
|
||||||
@ -1,67 +1,7 @@
|
|||||||
import { fillArray } from '../utils/helpers';
|
import { fillArray } from '../utils/helpers';
|
||||||
|
|
||||||
const AXIS_TICK_LENGTH = 6;
|
|
||||||
const LABEL_MARGIN = 4;
|
|
||||||
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
const MIN_BAR_PERCENT_HEIGHT = 0.01;
|
||||||
|
|
||||||
export function verticalLineProps(start, height, label='down') {
|
|
||||||
//
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getXLineProps(totalHeight, mode) {
|
|
||||||
let startAt = totalHeight + 6, height, textStartAt, axisLineClass = '';
|
|
||||||
if(mode === 'span') { // long spanning lines
|
|
||||||
startAt = -7;
|
|
||||||
height = totalHeight + 15;
|
|
||||||
textStartAt = totalHeight + 25;
|
|
||||||
} else if(mode === 'tick'){ // short label lines
|
|
||||||
startAt = totalHeight;
|
|
||||||
height = 6;
|
|
||||||
textStartAt = 9;
|
|
||||||
axisLineClass = 'x-axis-label';
|
|
||||||
}
|
|
||||||
|
|
||||||
return [startAt, height, textStartAt, axisLineClass];
|
|
||||||
}
|
|
||||||
|
|
||||||
// export function getYLineProps(totalWidth, mode, specific=false) {
|
|
||||||
export function getYLineProps(totalWidth, mode) {
|
|
||||||
// if(specific) {
|
|
||||||
// return[totalWidth, totalWidth + 5, 'specific-value', 0];
|
|
||||||
// }
|
|
||||||
let width, text_end_at = -9, axisLineClass = '', startAt = 0;
|
|
||||||
if(mode === 'span') { // long spanning lines
|
|
||||||
width = totalWidth + 6;
|
|
||||||
startAt = -6;
|
|
||||||
} else if(mode === 'tick'){ // short label lines
|
|
||||||
width = -6;
|
|
||||||
axisLineClass = 'y-axis-label';
|
|
||||||
}
|
|
||||||
|
|
||||||
return [width, text_end_at, axisLineClass, startAt];
|
|
||||||
}
|
|
||||||
|
|
||||||
// let char_width = 8;
|
|
||||||
// let allowed_space = avg_unit_width * 1.5;
|
|
||||||
// let allowed_letters = allowed_space / 8;
|
|
||||||
|
|
||||||
// return values.map((value, i) => {
|
|
||||||
// let space_taken = getStringWidth(value, char_width) + 2;
|
|
||||||
// if(space_taken > allowed_space) {
|
|
||||||
// if(is_series) {
|
|
||||||
// // Skip some axis lines if X axis is a series
|
|
||||||
// let skips = 1;
|
|
||||||
// while((space_taken/skips)*2 > allowed_space) {
|
|
||||||
// skips++;
|
|
||||||
// }
|
|
||||||
// if(i % skips !== 0) {
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// value = value.slice(0, allowed_letters-3) + " ...";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||||
let height, y;
|
let height, y;
|
||||||
if (yTop <= zeroLine) {
|
if (yTop <= zeroLine) {
|
||||||
@ -96,3 +36,24 @@ export function equilizeNoOfElements(array1, array2,
|
|||||||
}
|
}
|
||||||
return [array1, array2];
|
return [array1, array2];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// let char_width = 8;
|
||||||
|
// let allowed_space = avgUnitWidth * 1.5;
|
||||||
|
// let allowed_letters = allowed_space / 8;
|
||||||
|
|
||||||
|
// return values.map((value, i) => {
|
||||||
|
// let space_taken = getStringWidth(value, char_width) + 2;
|
||||||
|
// if(space_taken > allowed_space) {
|
||||||
|
// if(is_series) {
|
||||||
|
// // Skip some axis lines if X axis is a series
|
||||||
|
// let skips = 1;
|
||||||
|
// while((space_taken/skips)*2 > allowed_space) {
|
||||||
|
// skips++;
|
||||||
|
// }
|
||||||
|
// if(i % skips !== 0) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// value = value.slice(0, allowed_letters-3) + " ...";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
import { getBarHeightAndYAttr, getXLineProps, getYLineProps } from './draw-utils';
|
import { getBarHeightAndYAttr } from './draw-utils';
|
||||||
|
|
||||||
const X_LABEL_CLASS = 'x-value-text';
|
const AXIS_TICK_LENGTH = 6;
|
||||||
const Y_LABEL_CLASS = 'y-value-text';
|
const LABEL_MARGIN = 4;
|
||||||
|
const FONT_SIZE = 10;
|
||||||
// const X_AXIS_LINE_CLASS = 'x-value-text';
|
|
||||||
// const Y_AXIS_LINE_CLASS = 'y-value-text';
|
|
||||||
|
|
||||||
function $(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;
|
||||||
@ -134,122 +132,133 @@ export function makeText(className, x, y, content) {
|
|||||||
className: className,
|
className: className,
|
||||||
x: x,
|
x: x,
|
||||||
y: y,
|
y: y,
|
||||||
dy: '.32em',
|
dy: (FONT_SIZE / 2) + 'px',
|
||||||
|
'font-size': FONT_SIZE + 'px',
|
||||||
innerHTML: content
|
innerHTML: content
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export var AxisChartRenderer = (function() {
|
export function makeVertXLine(x, label, totalHeight, mode) {
|
||||||
var AxisChartRenderer = function(totalHeight, totalWidth, zeroLine, avgUnitWidth, xAxisMode, yAxisMode) {
|
let height = mode === 'span' ? -1 * AXIS_TICK_LENGTH : totalHeight;
|
||||||
this.totalHeight = totalHeight;
|
|
||||||
this.totalWidth = totalWidth;
|
|
||||||
this.zeroLine = zeroLine;
|
|
||||||
this.avgUnitWidth = avgUnitWidth;
|
|
||||||
this.xAxisMode = xAxisMode;
|
|
||||||
this.yAxisMode = yAxisMode;
|
|
||||||
};
|
|
||||||
|
|
||||||
AxisChartRenderer.prototype = {
|
let l = createSVG('line', {
|
||||||
bar: function (x, yTop, args, color, index, datasetIndex, noOfDatasets) {
|
x1: 0,
|
||||||
let totalWidth = this.avgUnitWidth - args.spaceWidth;
|
x2: 0,
|
||||||
let startX = x - totalWidth/2;
|
y1: totalHeight + AXIS_TICK_LENGTH,
|
||||||
|
y2: height
|
||||||
|
});
|
||||||
|
|
||||||
let width = totalWidth / noOfDatasets;
|
let text = createSVG('text', {
|
||||||
let currentX = startX + width * datasetIndex;
|
x: 0,
|
||||||
|
y: totalHeight + AXIS_TICK_LENGTH + LABEL_MARGIN,
|
||||||
|
dy: FONT_SIZE + 'px',
|
||||||
|
'font-size': FONT_SIZE + 'px',
|
||||||
|
'text-anchor': 'middle',
|
||||||
|
innerHTML: label
|
||||||
|
});
|
||||||
|
|
||||||
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
let line = createSVG('g', {
|
||||||
|
transform: `translate(${ x }, 0)`
|
||||||
|
});
|
||||||
|
|
||||||
return createSVG('rect', {
|
line.appendChild(l);
|
||||||
className: `bar mini`,
|
line.appendChild(text);
|
||||||
style: `fill: ${color}`,
|
|
||||||
'data-point-index': index,
|
|
||||||
x: currentX,
|
|
||||||
y: y,
|
|
||||||
width: width,
|
|
||||||
height: height
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
dot: function(x, y, args, color, index) {
|
return line;
|
||||||
return createSVG('circle', {
|
}
|
||||||
style: `fill: ${color}`,
|
|
||||||
'data-point-index': index,
|
|
||||||
cx: x,
|
|
||||||
cy: y,
|
|
||||||
r: args.radius
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
xLine: function(x, label, mode=this.xAxisMode) {
|
export function makeHoriYLine(y, label, totalWidth, mode) {
|
||||||
// Draw X axis line in span/tick mode with optional label
|
let lineType = '';
|
||||||
let [startAt, height, textStartAt, axisLineClass] = getXLineProps(this.totalHeight, mode);
|
let width = mode === 'span' ? totalWidth + AXIS_TICK_LENGTH : AXIS_TICK_LENGTH;
|
||||||
let l = createSVG('line', {
|
|
||||||
x1: 0,
|
|
||||||
x2: 0,
|
|
||||||
y1: startAt,
|
|
||||||
y2: height
|
|
||||||
});
|
|
||||||
|
|
||||||
let text = createSVG('text', {
|
let l = createSVG('line', {
|
||||||
className: X_LABEL_CLASS,
|
className: lineType === "dashed" ? "dashed": "",
|
||||||
x: 0,
|
x1: -1 * AXIS_TICK_LENGTH,
|
||||||
y: textStartAt,
|
x2: width,
|
||||||
dy: '.71em',
|
y1: 0,
|
||||||
innerHTML: label
|
y2: 0
|
||||||
});
|
});
|
||||||
|
|
||||||
let line = createSVG('g', {
|
let text = createSVG('text', {
|
||||||
className: `tick ${axisLineClass}`,
|
x: -1 * (LABEL_MARGIN + AXIS_TICK_LENGTH),
|
||||||
transform: `translate(${ x }, 0)`
|
y: 0,
|
||||||
});
|
dy: (FONT_SIZE / 2 - 2) + 'px',
|
||||||
|
'font-size': FONT_SIZE + 'px',
|
||||||
|
'text-anchor': 'end',
|
||||||
|
innerHTML: label+""
|
||||||
|
});
|
||||||
|
|
||||||
line.appendChild(l);
|
let line = createSVG('g', {
|
||||||
line.appendChild(text);
|
transform: `translate(0, ${y})`,
|
||||||
|
'stroke-opacity': 1
|
||||||
|
});
|
||||||
|
|
||||||
return line;
|
if(text === 0 || text === '0') {
|
||||||
},
|
line.style.stroke = "rgba(27, 31, 35, 0.6)";
|
||||||
|
}
|
||||||
|
|
||||||
yLine: function(y, label, mode=this.yAxisMode) {
|
line.appendChild(l);
|
||||||
// TODO: stroke type
|
line.appendChild(text);
|
||||||
let lineType = '';
|
|
||||||
|
|
||||||
let [width, textEndAt, axisLineClass, startAt] = getYLineProps(this.totalWidth, mode);
|
return line;
|
||||||
let l = createSVG('line', {
|
}
|
||||||
className: lineType === "dashed" ? "dashed": "",
|
|
||||||
x1: startAt,
|
|
||||||
x2: width,
|
|
||||||
y1: 0,
|
|
||||||
y2: 0
|
|
||||||
});
|
|
||||||
|
|
||||||
let text = createSVG('text', {
|
export class AxisChartRenderer {
|
||||||
className: Y_LABEL_CLASS,
|
constructor(state) {
|
||||||
x: textEndAt,
|
this.updateState(state);
|
||||||
y: 0,
|
}
|
||||||
dy: '.32em',
|
|
||||||
innerHTML: label+""
|
|
||||||
});
|
|
||||||
|
|
||||||
let line = createSVG('g', {
|
updateState(state) {
|
||||||
className: `tick ${axisLineClass}`,
|
this.totalHeight = state.totalHeight;
|
||||||
transform: `translate(0, ${y})`,
|
this.totalWidth = state.totalWidth;
|
||||||
'stroke-opacity': 1
|
this.zeroLine = state.zeroLine;
|
||||||
});
|
this.avgUnitWidth = state.avgUnitWidth;
|
||||||
|
this.xAxisMode = state.xAxisMode;
|
||||||
|
this.yAxisMode = state.yAxisMode;
|
||||||
|
}
|
||||||
|
|
||||||
// if(darker) {
|
bar(x, yTop, args, color, index, datasetIndex, noOfDatasets) {
|
||||||
// line.style.stroke = "rgba(27, 31, 35, 0.6)";
|
let totalWidth = this.avgUnitWidth - args.spaceWidth;
|
||||||
// }
|
let startX = x - totalWidth/2;
|
||||||
|
|
||||||
line.appendChild(l);
|
let width = totalWidth / noOfDatasets;
|
||||||
line.appendChild(text);
|
let currentX = startX + width * datasetIndex;
|
||||||
|
|
||||||
return line;
|
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
||||||
},
|
|
||||||
|
|
||||||
xRegion: function(x1, x2, label) { },
|
return createSVG('rect', {
|
||||||
|
className: `bar mini`,
|
||||||
|
style: `fill: ${color}`,
|
||||||
|
'data-point-index': index,
|
||||||
|
x: currentX,
|
||||||
|
y: y,
|
||||||
|
width: width,
|
||||||
|
height: height
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
yRegion: function(y1, y2, label) { }
|
dot(x, y, args, color, index) {
|
||||||
};
|
return createSVG('circle', {
|
||||||
|
style: `fill: ${color}`,
|
||||||
|
'data-point-index': index,
|
||||||
|
cx: x,
|
||||||
|
cy: y,
|
||||||
|
r: args.radius
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return AxisChartRenderer;
|
xLine(x, label, mode=this.xAxisMode) {
|
||||||
})();
|
// Draw X axis line in span/tick mode with optional label
|
||||||
|
return makeVertXLine(x, label, this.totalHeight, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
yLine(y, label, mode=this.yAxisMode) {
|
||||||
|
return makeHoriYLine(y, label, this.totalWidth, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
xMarker() {}
|
||||||
|
yMarker() {}
|
||||||
|
|
||||||
|
xRegion() {}
|
||||||
|
yRegion() {}
|
||||||
|
}
|
||||||
|
|||||||
@ -51,7 +51,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.axis, .chart-label {
|
.axis, .chart-label {
|
||||||
font-size: 11px;
|
|
||||||
fill: #555b51;
|
fill: #555b51;
|
||||||
line {
|
line {
|
||||||
stroke: #dadada;
|
stroke: #dadada;
|
||||||
@ -78,17 +77,18 @@
|
|||||||
line.dashed {
|
line.dashed {
|
||||||
stroke-dasharray: 5,3;
|
stroke-dasharray: 5,3;
|
||||||
}
|
}
|
||||||
.tick {
|
.axis-line {
|
||||||
&.x-axis-label {
|
// &.x-axis-label {
|
||||||
display: block;
|
// display: block;
|
||||||
}
|
// }
|
||||||
|
// TODO: hack dy attr to be settable via styles
|
||||||
.specific-value {
|
.specific-value {
|
||||||
text-anchor: start;
|
text-anchor: start;
|
||||||
}
|
}
|
||||||
.y-value-text {
|
.y-line {
|
||||||
text-anchor: end;
|
text-anchor: end;
|
||||||
}
|
}
|
||||||
.x-value-text {
|
.x-line {
|
||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user