Animator object, camelCase all utils
This commit is contained in:
parent
cd8d750152
commit
7c4e0dcdf8
349
dist/frappe-charts.esm.js
vendored
349
dist/frappe-charts.esm.js
vendored
@ -102,7 +102,29 @@ $.fire = (target, type, properties) => {
|
|||||||
return target.dispatchEvent(evt);
|
return target.dispatchEvent(evt);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Constants used
|
function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||||
|
let height, y;
|
||||||
|
if (yTop <= zeroLine) {
|
||||||
|
height = zeroLine - yTop;
|
||||||
|
y = yTop;
|
||||||
|
|
||||||
|
// In case of invisible bars
|
||||||
|
if(height === 0) {
|
||||||
|
height = totalHeight * 0.01;
|
||||||
|
y -= height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = yTop - zeroLine;
|
||||||
|
y = zeroLine;
|
||||||
|
|
||||||
|
// In case of invisible bars
|
||||||
|
if(height === 0) {
|
||||||
|
height = totalHeight * 0.01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [height, y];
|
||||||
|
}
|
||||||
|
|
||||||
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;
|
||||||
@ -153,7 +175,7 @@ function renderVerticalGradient(svgDefElem, gradientId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setGradientStop(gradElem, offset, color, opacity) {
|
function setGradientStop(gradElem, offset, color, opacity) {
|
||||||
createSVG('stop', {
|
return createSVG('stop', {
|
||||||
'inside': gradElem,
|
'inside': gradElem,
|
||||||
'style': `stop-color: ${color}`,
|
'style': `stop-color: ${color}`,
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
@ -298,58 +320,34 @@ function makeYLine(startAt, width, textEndAt, point, labelClass, axisLineClass,
|
|||||||
}
|
}
|
||||||
|
|
||||||
var UnitRenderer = (function() {
|
var UnitRenderer = (function() {
|
||||||
var UnitRenderer = function(total_height, zero_line, avg_unit_width) {
|
var UnitRenderer = function(totalHeight, zeroLine, avgUnitWidth) {
|
||||||
this.total_height = total_height;
|
this.totalHeight = totalHeight;
|
||||||
this.zero_line = zero_line;
|
this.zeroLine = zeroLine;
|
||||||
this.avg_unit_width = avg_unit_width;
|
this.avgUnitWidth = avgUnitWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
function get_bar_height_and_y_attr(y_top, zero_line, total_height) {
|
|
||||||
let height, y;
|
|
||||||
if (y_top <= zero_line) {
|
|
||||||
height = zero_line - y_top;
|
|
||||||
y = y_top;
|
|
||||||
|
|
||||||
// In case of invisible bars
|
|
||||||
if(height === 0) {
|
|
||||||
height = total_height * 0.01;
|
|
||||||
y -= height;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
height = y_top - zero_line;
|
|
||||||
y = zero_line;
|
|
||||||
|
|
||||||
// In case of invisible bars
|
|
||||||
if(height === 0) {
|
|
||||||
height = total_height * 0.01;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [height, y];
|
|
||||||
}
|
|
||||||
|
|
||||||
UnitRenderer.prototype = {
|
UnitRenderer.prototype = {
|
||||||
draw_bar: function (x, y_top, args, color, index, dataset_index, no_of_datasets) {
|
bar: function (x, yTop, args, color, index, datasetIndex, noOfDatasets) {
|
||||||
let total_width = this.avg_unit_width - args.space_width;
|
let totalWidth = this.avgUnitWidth - args.spaceWidth;
|
||||||
let start_x = x - total_width/2;
|
let startX = x - totalWidth/2;
|
||||||
|
|
||||||
let width = total_width / no_of_datasets;
|
let width = totalWidth / noOfDatasets;
|
||||||
let current_x = start_x + width * dataset_index;
|
let currentX = startX + width * datasetIndex;
|
||||||
|
|
||||||
let [height, y] = get_bar_height_and_y_attr(y_top, this.zero_line, this.total_height);
|
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
||||||
|
|
||||||
return createSVG('rect', {
|
return createSVG('rect', {
|
||||||
className: `bar mini`,
|
className: `bar mini`,
|
||||||
style: `fill: ${color}`,
|
style: `fill: ${color}`,
|
||||||
'data-point-index': index,
|
'data-point-index': index,
|
||||||
x: current_x,
|
x: currentX,
|
||||||
y: y,
|
y: y,
|
||||||
width: width,
|
width: width,
|
||||||
height: height
|
height: height
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
draw_dot: function(x, y, args, color, index) {
|
dot: function(x, y, args, color, index) {
|
||||||
return createSVG('circle', {
|
return createSVG('circle', {
|
||||||
style: `fill: ${color}`,
|
style: `fill: ${color}`,
|
||||||
'data-point-index': index,
|
'data-point-index': index,
|
||||||
@ -357,28 +355,65 @@ var UnitRenderer = (function() {
|
|||||||
cy: y,
|
cy: y,
|
||||||
r: args.radius
|
r: args.radius
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
animate_bar: function(bar_obj, x, y_top, index, no_of_datasets) {
|
|
||||||
let start = x - this.avg_unit_width/4;
|
|
||||||
let width = (this.avg_unit_width/2)/no_of_datasets;
|
|
||||||
let [height, y] = get_bar_height_and_y_attr(y_top, this.zero_line, this.total_height);
|
|
||||||
|
|
||||||
x = start + (width * index);
|
|
||||||
|
|
||||||
return [bar_obj, {width: width, height: height, x: x, y: y}, 350, "easein"];
|
|
||||||
// bar.animate({height: args.new_height, y: y_top}, 350, mina.easein);
|
|
||||||
},
|
|
||||||
|
|
||||||
animate_dot: function(dot_obj, x, y_top) {
|
|
||||||
return [dot_obj, {cx: x, cy: y_top}, 350, "easein"];
|
|
||||||
// dot.animate({cy: y_top}, 350, mina.easein);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return UnitRenderer;
|
return UnitRenderer;
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
var Animator = (function() {
|
||||||
|
var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) {
|
||||||
|
// constants
|
||||||
|
this.totalHeight = totalHeight;
|
||||||
|
this.totalWidth = totalWidth;
|
||||||
|
|
||||||
|
// changeables
|
||||||
|
this.avgUnitWidth = avgUnitWidth;
|
||||||
|
this.zeroLine = zeroLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
Animator.prototype = {
|
||||||
|
bar: function(barObj, x, yTop, index, noOfDatasets) {
|
||||||
|
let start = x - this.avgUnitWidth/4;
|
||||||
|
let width = (this.avgUnitWidth/2)/noOfDatasets;
|
||||||
|
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
||||||
|
|
||||||
|
x = start + (width * index);
|
||||||
|
|
||||||
|
return [barObj, {width: width, height: height, x: x, y: y}, 350, "easein"];
|
||||||
|
// bar.animate({height: args.newHeight, y: yTop}, 350, mina.easein);
|
||||||
|
},
|
||||||
|
|
||||||
|
dot: function(dotObj, x, yTop) {
|
||||||
|
return [dotObj, {cx: x, cy: yTop}, 350, "easein"];
|
||||||
|
// dot.animate({cy: yTop}, 350, mina.easein);
|
||||||
|
},
|
||||||
|
|
||||||
|
path: function(d, pathStr) {
|
||||||
|
let pathComponents = [];
|
||||||
|
const animPath = [{unit: d.path, object: d, key: 'path'}, {d:"M"+pathStr}, 350, "easein"];
|
||||||
|
pathComponents.push(animPath);
|
||||||
|
|
||||||
|
if(d.regionPath) {
|
||||||
|
let regStartPt = `0,${this.zeroLine}L`;
|
||||||
|
let regEndPt = `L${this.totalWidth}, ${this.zeroLine}`;
|
||||||
|
|
||||||
|
const animRegion = [
|
||||||
|
{unit: d.regionPath, object: d, key: 'regionPath'},
|
||||||
|
{d:"M" + regStartPt + pathStr + regEndPt},
|
||||||
|
350,
|
||||||
|
"easein"
|
||||||
|
];
|
||||||
|
pathComponents.push(animRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathComponents;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return Animator;
|
||||||
|
})();
|
||||||
|
|
||||||
// Leveraging SMIL Animations
|
// Leveraging SMIL Animations
|
||||||
|
|
||||||
const EASING = {
|
const EASING = {
|
||||||
@ -390,52 +425,52 @@ const EASING = {
|
|||||||
easeinout: "0.42 0 0.58 1"
|
easeinout: "0.42 0 0.58 1"
|
||||||
};
|
};
|
||||||
|
|
||||||
function animateSVG(element, props, dur, easing_type="linear", type=undefined, old_values={}) {
|
function animateSVG(element, props, dur, easingType="linear", type=undefined, oldValues={}) {
|
||||||
|
|
||||||
let anim_element = element.cloneNode(true);
|
let animElement = element.cloneNode(true);
|
||||||
let new_element = element.cloneNode(true);
|
let newElement = element.cloneNode(true);
|
||||||
|
|
||||||
for(var attributeName in props) {
|
for(var attributeName in props) {
|
||||||
let animate_element;
|
let animateElement;
|
||||||
if(attributeName === 'transform') {
|
if(attributeName === 'transform') {
|
||||||
animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
|
animateElement = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
|
||||||
} else {
|
} else {
|
||||||
animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animate");
|
animateElement = document.createElementNS("http://www.w3.org/2000/svg", "animate");
|
||||||
}
|
}
|
||||||
let current_value = old_values[attributeName] || element.getAttribute(attributeName);
|
let currentValue = oldValues[attributeName] || element.getAttribute(attributeName);
|
||||||
let value = props[attributeName];
|
let value = props[attributeName];
|
||||||
|
|
||||||
let anim_attr = {
|
let animAttr = {
|
||||||
attributeName: attributeName,
|
attributeName: attributeName,
|
||||||
from: current_value,
|
from: currentValue,
|
||||||
to: value,
|
to: value,
|
||||||
begin: "0s",
|
begin: "0s",
|
||||||
dur: dur/1000 + "s",
|
dur: dur/1000 + "s",
|
||||||
values: current_value + ";" + value,
|
values: currentValue + ";" + value,
|
||||||
keySplines: EASING[easing_type],
|
keySplines: EASING[easingType],
|
||||||
keyTimes: "0;1",
|
keyTimes: "0;1",
|
||||||
calcMode: "spline",
|
calcMode: "spline",
|
||||||
fill: 'freeze'
|
fill: 'freeze'
|
||||||
};
|
};
|
||||||
|
|
||||||
if(type) {
|
if(type) {
|
||||||
anim_attr["type"] = type;
|
animAttr["type"] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i in anim_attr) {
|
for (var i in animAttr) {
|
||||||
animate_element.setAttribute(i, anim_attr[i]);
|
animateElement.setAttribute(i, animAttr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
anim_element.appendChild(animate_element);
|
animElement.appendChild(animateElement);
|
||||||
|
|
||||||
if(type) {
|
if(type) {
|
||||||
new_element.setAttribute(attributeName, `translate(${value})`);
|
newElement.setAttribute(attributeName, `translate(${value})`);
|
||||||
} else {
|
} else {
|
||||||
new_element.setAttribute(attributeName, value);
|
newElement.setAttribute(attributeName, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [anim_element, new_element];
|
return [animElement, newElement];
|
||||||
}
|
}
|
||||||
|
|
||||||
function transform(element, style) { // eslint-disable-line no-unused-vars
|
function transform(element, style) { // eslint-disable-line no-unused-vars
|
||||||
@ -446,39 +481,39 @@ function transform(element, style) { // eslint-disable-line no-unused-vars
|
|||||||
element.style.oTransform = style;
|
element.style.oTransform = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
function runSVGAnimation(svg_container, elements) {
|
function runSVGAnimation(svgContainer, elements) {
|
||||||
let new_elements = [];
|
let newElements = [];
|
||||||
let anim_elements = [];
|
let animElements = [];
|
||||||
|
|
||||||
elements.map(element => {
|
elements.map(element => {
|
||||||
let obj = element[0];
|
let obj = element[0];
|
||||||
let parent = obj.unit.parentNode;
|
let parent = obj.unit.parentNode;
|
||||||
|
|
||||||
let anim_element, new_element;
|
let animElement, newElement;
|
||||||
|
|
||||||
element[0] = obj.unit;
|
element[0] = obj.unit;
|
||||||
[anim_element, new_element] = animateSVG(...element);
|
[animElement, newElement] = animateSVG(...element);
|
||||||
|
|
||||||
new_elements.push(new_element);
|
newElements.push(newElement);
|
||||||
anim_elements.push([anim_element, parent]);
|
animElements.push([animElement, parent]);
|
||||||
|
|
||||||
parent.replaceChild(anim_element, obj.unit);
|
parent.replaceChild(animElement, obj.unit);
|
||||||
|
|
||||||
if(obj.array) {
|
if(obj.array) {
|
||||||
obj.array[obj.index] = new_element;
|
obj.array[obj.index] = newElement;
|
||||||
} else {
|
} else {
|
||||||
obj.object[obj.key] = new_element;
|
obj.object[obj.key] = newElement;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let anim_svg = svg_container.cloneNode(true);
|
let animSvg = svgContainer.cloneNode(true);
|
||||||
|
|
||||||
anim_elements.map((anim_element, i) => {
|
animElements.map((animElement, i) => {
|
||||||
anim_element[1].replaceChild(new_elements[i], anim_element[0]);
|
animElement[1].replaceChild(newElements[i], animElement[0]);
|
||||||
elements[i][0] = new_elements[i];
|
elements[i][0] = newElements[i];
|
||||||
});
|
});
|
||||||
|
|
||||||
return anim_svg;
|
return animSvg;
|
||||||
}
|
}
|
||||||
|
|
||||||
function normalize(x) {
|
function normalize(x) {
|
||||||
@ -661,7 +696,7 @@ function getMaxCheckpoint(value, distribution) {
|
|||||||
* Returns the value of a number upto 2 decimal places.
|
* Returns the value of a number upto 2 decimal places.
|
||||||
* @param {Number} d Any number
|
* @param {Number} d Any number
|
||||||
*/
|
*/
|
||||||
function float_2(d) {
|
function floatTwo(d) {
|
||||||
return parseFloat(d.toFixed(2));
|
return parseFloat(d.toFixed(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -670,13 +705,13 @@ function float_2(d) {
|
|||||||
* @param {Array} arr1 First array
|
* @param {Array} arr1 First array
|
||||||
* @param {Array} arr2 Second array
|
* @param {Array} arr2 Second array
|
||||||
*/
|
*/
|
||||||
function arrays_equal(arr1, arr2) {
|
function arraysEqual(arr1, arr2) {
|
||||||
if(arr1.length !== arr2.length) return false;
|
if(arr1.length !== arr2.length) return false;
|
||||||
let are_equal = true;
|
let areEqual = true;
|
||||||
arr1.map((d, i) => {
|
arr1.map((d, i) => {
|
||||||
if(arr2[i] !== d) are_equal = false;
|
if(arr2[i] !== d) areEqual = false;
|
||||||
});
|
});
|
||||||
return are_equal;
|
return areEqual;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -688,10 +723,10 @@ function arrays_equal(arr1, arr2) {
|
|||||||
/**
|
/**
|
||||||
* Returns pixel width of string.
|
* Returns pixel width of string.
|
||||||
* @param {String} string
|
* @param {String} string
|
||||||
* @param {Number} char_width Width of single char in pixels
|
* @param {Number} charWidth Width of single char in pixels
|
||||||
*/
|
*/
|
||||||
function get_string_width(string, char_width) {
|
function getStringWidth(string, charWidth) {
|
||||||
return (string+"").length * char_width;
|
return (string+"").length * charWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
class SvgTip {
|
class SvgTip {
|
||||||
@ -834,32 +869,32 @@ const PRESET_COLOR_MAP = {
|
|||||||
const DEFAULT_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
|
const DEFAULT_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
|
||||||
'yellow', 'green', 'light-green', 'purple', 'magenta'];
|
'yellow', 'green', 'light-green', 'purple', 'magenta'];
|
||||||
|
|
||||||
function limit_color(r){
|
function limitColor(r){
|
||||||
if (r > 255) return 255;
|
if (r > 255) return 255;
|
||||||
else if (r < 0) return 0;
|
else if (r < 0) return 0;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
function lighten_darken_color(color, amt) {
|
function lightenDarkenColor(color, amt) {
|
||||||
let col = get_color(color);
|
let col = getColor(color);
|
||||||
let usePound = false;
|
let usePound = false;
|
||||||
if (col[0] == "#") {
|
if (col[0] == "#") {
|
||||||
col = col.slice(1);
|
col = col.slice(1);
|
||||||
usePound = true;
|
usePound = true;
|
||||||
}
|
}
|
||||||
let num = parseInt(col,16);
|
let num = parseInt(col,16);
|
||||||
let r = limit_color((num >> 16) + amt);
|
let r = limitColor((num >> 16) + amt);
|
||||||
let b = limit_color(((num >> 8) & 0x00FF) + amt);
|
let b = limitColor(((num >> 8) & 0x00FF) + amt);
|
||||||
let g = limit_color((num & 0x0000FF) + amt);
|
let g = limitColor((num & 0x0000FF) + amt);
|
||||||
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
|
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
function is_valid_color(string) {
|
function isValidColor(string) {
|
||||||
// https://stackoverflow.com/a/8027444/6495043
|
// https://stackoverflow.com/a/8027444/6495043
|
||||||
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(string);
|
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
const get_color = (color) => {
|
const getColor = (color) => {
|
||||||
return PRESET_COLOR_MAP[color] || color;
|
return PRESET_COLOR_MAP[color] || color;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -961,7 +996,7 @@ class BaseChart {
|
|||||||
this.colors = DEFAULT_COLORS;
|
this.colors = DEFAULT_COLORS;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.colors = this.colors.map(color => get_color(color));
|
this.colors = this.colors.map(color => getColor(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
set_margins(height) {
|
set_margins(height) {
|
||||||
@ -1019,7 +1054,7 @@ class BaseChart {
|
|||||||
let special_values_width = 0;
|
let special_values_width = 0;
|
||||||
let char_width = 8;
|
let char_width = 8;
|
||||||
this.specific_values.map(val => {
|
this.specific_values.map(val => {
|
||||||
let str_width = get_string_width((val.title + ""), char_width);
|
let str_width = getStringWidth((val.title + ""), char_width);
|
||||||
if(str_width > special_values_width) {
|
if(str_width > special_values_width) {
|
||||||
special_values_width = str_width - 40;
|
special_values_width = str_width - 40;
|
||||||
}
|
}
|
||||||
@ -1197,7 +1232,7 @@ class AxisChart extends BaseChart {
|
|||||||
this.x_old_axis_positions = this.x_axis_positions.slice();
|
this.x_old_axis_positions = this.x_axis_positions.slice();
|
||||||
}
|
}
|
||||||
this.x_axis_positions = this.x.map((d, i) =>
|
this.x_axis_positions = this.x.map((d, i) =>
|
||||||
float_2(this.x_offset + i * this.avg_unit_width));
|
floatTwo(this.x_offset + i * this.avg_unit_width));
|
||||||
|
|
||||||
if(!this.x_old_axis_positions) {
|
if(!this.x_old_axis_positions) {
|
||||||
this.x_old_axis_positions = this.x_axis_positions.slice();
|
this.x_old_axis_positions = this.x_axis_positions.slice();
|
||||||
@ -1314,7 +1349,7 @@ class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
this.x_axis_group.textContent = '';
|
this.x_axis_group.textContent = '';
|
||||||
this.x.map((point, i) => {
|
this.x.map((point, i) => {
|
||||||
let space_taken = get_string_width(point, char_width) + 2;
|
let space_taken = getStringWidth(point, char_width) + 2;
|
||||||
if(space_taken > allowed_space) {
|
if(space_taken > allowed_space) {
|
||||||
if(this.is_series) {
|
if(this.is_series) {
|
||||||
// Skip some axis lines if X axis is a series
|
// Skip some axis lines if X axis is a series
|
||||||
@ -1457,7 +1492,7 @@ class AxisChart extends BaseChart {
|
|||||||
let unit_renderer = new UnitRenderer(this.height, this.zero_line, this.avg_unit_width);
|
let unit_renderer = new UnitRenderer(this.height, this.zero_line, this.avg_unit_width);
|
||||||
|
|
||||||
y_values.map((y, i) => {
|
y_values.map((y, i) => {
|
||||||
let data_unit = unit_renderer['draw_' + unit.type](
|
let data_unit = unit_renderer[unit.type](
|
||||||
x_values[i],
|
x_values[i],
|
||||||
y,
|
y,
|
||||||
unit.args,
|
unit.args,
|
||||||
@ -1561,7 +1596,7 @@ class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
this.make_new_units_for_dataset(
|
this.make_new_units_for_dataset(
|
||||||
this.x_axis_positions,
|
this.x_axis_positions,
|
||||||
this.y_sums.map( val => float_2(this.zero_line - val * this.multiplier)),
|
this.y_sums.map( val => floatTwo(this.zero_line - val * this.multiplier)),
|
||||||
'#f0f4f7',
|
'#f0f4f7',
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ -1636,17 +1671,23 @@ class AxisChart extends BaseChart {
|
|||||||
this.setup_x();
|
this.setup_x();
|
||||||
this.setup_y();
|
this.setup_y();
|
||||||
|
|
||||||
|
// Change in data, so calculate dependencies
|
||||||
|
this.calc_y_dependencies();
|
||||||
|
|
||||||
|
// Got the values? Now begin drawing
|
||||||
|
this.animator = new Animator(this.height, this.width, this.zero_line, this.avg_unit_width);
|
||||||
|
|
||||||
// Animate only if positions have changed
|
// Animate only if positions have changed
|
||||||
if(!arrays_equal(this.x_old_axis_positions, this.x_axis_positions)) {
|
if(!arraysEqual(this.x_old_axis_positions, this.x_axis_positions)) {
|
||||||
this.make_x_axis(true);
|
this.make_x_axis(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if(!this.updating) this.make_x_axis();
|
if(!this.updating) this.make_x_axis();
|
||||||
}, 350);
|
}, 350);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!arrays_equal(this.y_old_axis_values, this.y_axis_values) ||
|
if(!arraysEqual(this.y_old_axis_values, this.y_axis_values) ||
|
||||||
(this.old_specific_values &&
|
(this.old_specific_values &&
|
||||||
!arrays_equal(this.old_specific_values, this.specific_values))) {
|
!arraysEqual(this.old_specific_values, this.specific_values))) {
|
||||||
|
|
||||||
this.make_y_axis(true);
|
this.make_y_axis(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -1657,9 +1698,6 @@ class AxisChart extends BaseChart {
|
|||||||
}, 350);
|
}, 350);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change in data, so calculate dependencies
|
|
||||||
this.calc_y_dependencies();
|
|
||||||
|
|
||||||
this.animate_graphs();
|
this.animate_graphs();
|
||||||
|
|
||||||
// Trigger animation with the animatable elements in this.elements_to_animate
|
// Trigger animation with the animatable elements in this.elements_to_animate
|
||||||
@ -1728,35 +1766,18 @@ class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
animate_path(d, i, old_x, old_y, new_x, new_y) {
|
animate_path(d, i, old_x, old_y, new_x, new_y) {
|
||||||
// Animate path
|
const newPointsList = new_y.map((y, i) => (new_x[i] + ',' + y));
|
||||||
const new_points_list = new_y.map((y, i) => (new_x[i] + ',' + y));
|
const newPathStr = newPointsList.join("L");
|
||||||
const new_path_str = new_points_list.join("L");
|
this.elements_to_animate = this.elements_to_animate
|
||||||
|
.concat(this.animator['path'](d, newPathStr));
|
||||||
const path_args = [{unit: d.path, object: d, key: 'path'}, {d:"M"+new_path_str}, 350, "easein"];
|
|
||||||
this.elements_to_animate.push(path_args);
|
|
||||||
|
|
||||||
// Animate region
|
|
||||||
if(d.region_path) {
|
|
||||||
let reg_start_pt = `0,${this.zero_line}L`;
|
|
||||||
let reg_end_pt = `L${this.width},${this.zero_line}`;
|
|
||||||
|
|
||||||
const region_args = [
|
|
||||||
{unit: d.region_path, object: d, key: 'region_path'},
|
|
||||||
{d:"M" + reg_start_pt + new_path_str + reg_end_pt},
|
|
||||||
350,
|
|
||||||
"easein"
|
|
||||||
];
|
|
||||||
this.elements_to_animate.push(region_args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
animate_units(d, index, old_x, old_y, new_x, new_y) {
|
animate_units(d, index, old_x, old_y, new_x, new_y) {
|
||||||
let type = this.unit_args.type;
|
let type = this.unit_args.type;
|
||||||
let unit_renderer = new UnitRenderer(this.height, this.zero_line, this.avg_unit_width);
|
|
||||||
|
|
||||||
d.svg_units.map((unit, i) => {
|
d.svg_units.map((unit, i) => {
|
||||||
if(new_x[i] === undefined || new_y[i] === undefined) return;
|
if(new_x[i] === undefined || new_y[i] === undefined) return;
|
||||||
this.elements_to_animate.push(unit_renderer['animate_' + type](
|
this.elements_to_animate.push(this.animator[type](
|
||||||
{unit:unit, array:d.svg_units, index: i}, // unit, with info to replace where it came from in the data
|
{unit:unit, array:d.svg_units, index: i}, // unit, with info to replace where it came from in the data
|
||||||
new_x[i],
|
new_x[i],
|
||||||
new_y[i],
|
new_y[i],
|
||||||
@ -1780,8 +1801,8 @@ class AxisChart extends BaseChart {
|
|||||||
const last_new_y_pos = new_y[new_y.length - 1];
|
const last_new_y_pos = new_y[new_y.length - 1];
|
||||||
|
|
||||||
if(this.no_of_extra_pts >= 0) {
|
if(this.no_of_extra_pts >= 0) {
|
||||||
// First substitute current path with a squiggled one (looking the same but
|
// First substitute current path with a squiggled one
|
||||||
// having more points at end),
|
// (that looks the same but has more points at end),
|
||||||
// then animate to stretch it later to new points
|
// then animate to stretch it later to new points
|
||||||
// (new points already have more points)
|
// (new points already have more points)
|
||||||
|
|
||||||
@ -1991,7 +2012,7 @@ class AxisChart extends BaseChart {
|
|||||||
calc_y_dependencies() {
|
calc_y_dependencies() {
|
||||||
this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999);
|
this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999);
|
||||||
this.y.map(d => {
|
this.y.map(d => {
|
||||||
d.y_tops = d.values.map( val => float_2(this.zero_line - val * this.multiplier));
|
d.y_tops = d.values.map( val => floatTwo(this.zero_line - val * this.multiplier));
|
||||||
d.y_tops.map( (y_top, i) => {
|
d.y_tops.map( (y_top, i) => {
|
||||||
if(y_top < this.y_min_tops[i]) {
|
if(y_top < this.y_min_tops[i]) {
|
||||||
this.y_min_tops[i] = y_top;
|
this.y_min_tops[i] = y_top;
|
||||||
@ -2019,7 +2040,7 @@ class BarChart extends AxisChart {
|
|||||||
this.unit_args = {
|
this.unit_args = {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
args: {
|
args: {
|
||||||
space_width: this.avg_unit_width/2,
|
spaceWidth: this.avg_unit_width/2,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -2167,8 +2188,8 @@ class LineChart extends AxisChart {
|
|||||||
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.zero_line}L` + points_str + `L${this.width},${this.zero_line}`;
|
||||||
|
|
||||||
d.region_path = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
d.regionPath = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
||||||
this.paths_groups[i].appendChild(d.region_path);
|
this.paths_groups[i].appendChild(d.regionPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2482,7 +2503,7 @@ class PieChart extends BaseChart {
|
|||||||
const color = this.colors[i];
|
const color = this.colors[i];
|
||||||
if(flag){
|
if(flag){
|
||||||
transform(path,this.calTranslateByAngle(this.slicesProperties[i]));
|
transform(path,this.calTranslateByAngle(this.slicesProperties[i]));
|
||||||
path.style.fill = lighten_darken_color(color,50);
|
path.style.fill = lightenDarkenColor(color,50);
|
||||||
let g_off = $.offset(this.svg);
|
let g_off = $.offset(this.svg);
|
||||||
let x = e.pageX - g_off.left + 10;
|
let x = e.pageX - g_off.left + 10;
|
||||||
let y = e.pageY - g_off.top - 10;
|
let y = e.pageY - g_off.top - 10;
|
||||||
@ -2544,13 +2565,13 @@ class PieChart extends BaseChart {
|
|||||||
// Playing around with dates
|
// Playing around with dates
|
||||||
|
|
||||||
// https://stackoverflow.com/a/11252167/6495043
|
// https://stackoverflow.com/a/11252167/6495043
|
||||||
function treat_as_utc(date_str) {
|
function treatAsUtc(dateStr) {
|
||||||
let result = new Date(date_str);
|
let result = new Date(dateStr);
|
||||||
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_dd_mm_yyyy(date) {
|
function getDdMmYyyy(date) {
|
||||||
let dd = date.getDate();
|
let dd = date.getDate();
|
||||||
let mm = date.getMonth() + 1; // getMonth() is zero-based
|
let mm = date.getMonth() + 1; // getMonth() is zero-based
|
||||||
return [
|
return [
|
||||||
@ -2560,21 +2581,21 @@ function get_dd_mm_yyyy(date) {
|
|||||||
].join('-');
|
].join('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_weeks_between(start_date_str, end_date_str) {
|
function getWeeksBetween(startDateStr, endDateStr) {
|
||||||
return Math.ceil(get_days_between(start_date_str, end_date_str) / 7);
|
return Math.ceil(getDaysBetween(startDateStr, endDateStr) / 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
function get_days_between(start_date_str, end_date_str) {
|
function getDaysBetween(startDateStr, endDateStr) {
|
||||||
let milliseconds_per_day = 24 * 60 * 60 * 1000;
|
let millisecondsPerDay = 24 * 60 * 60 * 1000;
|
||||||
return (treat_as_utc(end_date_str) - treat_as_utc(start_date_str)) / milliseconds_per_day;
|
return (treatAsUtc(endDateStr) - treatAsUtc(startDateStr)) / millisecondsPerDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutates
|
// mutates
|
||||||
function add_days(date, number_of_days) {
|
function addDays(date, numberOfDays) {
|
||||||
date.setDate(date.getDate() + number_of_days);
|
date.setDate(date.getDate() + numberOfDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function get_month_name() {}
|
// export function getMonthName() {}
|
||||||
|
|
||||||
class Heatmap extends BaseChart {
|
class Heatmap extends BaseChart {
|
||||||
constructor({
|
constructor({
|
||||||
@ -2597,14 +2618,14 @@ class Heatmap extends BaseChart {
|
|||||||
this.count_label = count_label;
|
this.count_label = count_label;
|
||||||
|
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
this.start = start || add_days(today, 365);
|
this.start = start || addDays(today, 365);
|
||||||
|
|
||||||
legend_colors = legend_colors.slice(0, 5);
|
legend_colors = legend_colors.slice(0, 5);
|
||||||
this.legend_colors = this.validate_colors(legend_colors)
|
this.legend_colors = this.validate_colors(legend_colors)
|
||||||
? legend_colors
|
? legend_colors
|
||||||
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
|
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
|
||||||
|
|
||||||
// Hardcoded for a fixed 5-color theme,
|
// Fixed 5-color theme,
|
||||||
// More colors are difficult to parse visually
|
// More colors are difficult to parse visually
|
||||||
this.distribution_size = 5;
|
this.distribution_size = 5;
|
||||||
|
|
||||||
@ -2617,7 +2638,7 @@ class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
let valid = 1;
|
let valid = 1;
|
||||||
colors.forEach(function(string) {
|
colors.forEach(function(string) {
|
||||||
if(!is_valid_color(string)) {
|
if(!isValidColor(string)) {
|
||||||
valid = 0;
|
valid = 0;
|
||||||
console.warn('"' + string + '" is not a valid color.');
|
console.warn('"' + string + '" is not a valid color.');
|
||||||
}
|
}
|
||||||
@ -2636,12 +2657,12 @@ class Heatmap extends BaseChart {
|
|||||||
this.first_week_start = new Date(this.start.toDateString());
|
this.first_week_start = new Date(this.start.toDateString());
|
||||||
this.last_week_start = new Date(this.today.toDateString());
|
this.last_week_start = new Date(this.today.toDateString());
|
||||||
if(this.first_week_start.getDay() !== 7) {
|
if(this.first_week_start.getDay() !== 7) {
|
||||||
add_days(this.first_week_start, (-1) * this.first_week_start.getDay());
|
addDays(this.first_week_start, (-1) * this.first_week_start.getDay());
|
||||||
}
|
}
|
||||||
if(this.last_week_start.getDay() !== 7) {
|
if(this.last_week_start.getDay() !== 7) {
|
||||||
add_days(this.last_week_start, (-1) * this.last_week_start.getDay());
|
addDays(this.last_week_start, (-1) * this.last_week_start.getDay());
|
||||||
}
|
}
|
||||||
this.no_of_cols = get_weeks_between(this.first_week_start + '', this.last_week_start + '') + 1;
|
this.no_of_cols = getWeeksBetween(this.first_week_start + '', this.last_week_start + '') + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_width() {
|
set_width() {
|
||||||
@ -2699,7 +2720,7 @@ class Heatmap extends BaseChart {
|
|||||||
this.months.push(this.current_month + '');
|
this.months.push(this.current_month + '');
|
||||||
this.month_weeks[this.current_month] = 1;
|
this.month_weeks[this.current_month] = 1;
|
||||||
}
|
}
|
||||||
add_days(current_week_sunday, 7);
|
addDays(current_week_sunday, 7);
|
||||||
}
|
}
|
||||||
this.render_month_labels();
|
this.render_month_labels();
|
||||||
}
|
}
|
||||||
@ -2738,7 +2759,7 @@ class Heatmap extends BaseChart {
|
|||||||
let x = 13 + (index + week_col_change) * 12;
|
let x = 13 + (index + week_col_change) * 12;
|
||||||
|
|
||||||
let dataAttr = {
|
let dataAttr = {
|
||||||
'data-date': get_dd_mm_yyyy(current_date),
|
'data-date': getDdMmYyyy(current_date),
|
||||||
'data-value': data_value,
|
'data-value': data_value,
|
||||||
'data-day': current_date.getDay()
|
'data-day': current_date.getDay()
|
||||||
};
|
};
|
||||||
@ -2748,7 +2769,7 @@ class Heatmap extends BaseChart {
|
|||||||
data_group.appendChild(heatSquare);
|
data_group.appendChild(heatSquare);
|
||||||
|
|
||||||
let next_date = new Date(current_date);
|
let next_date = new Date(current_date);
|
||||||
add_days(next_date, 1);
|
addDays(next_date, 1);
|
||||||
if(next_date.getTime() > today_time) break;
|
if(next_date.getTime() > today_time) break;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
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
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
@ -1,8 +1,9 @@
|
|||||||
import $ from '../utils/dom';
|
import $ from '../utils/dom';
|
||||||
import { UnitRenderer, makeXLine, makeYLine } from '../utils/draw';
|
import { UnitRenderer, makeXLine, makeYLine } from '../utils/draw';
|
||||||
|
import { Animator } from '../utils/animate';
|
||||||
import { runSVGAnimation } from '../utils/animation';
|
import { runSVGAnimation } from '../utils/animation';
|
||||||
import { calcIntervals } from '../utils/intervals';
|
import { calcIntervals } from '../utils/intervals';
|
||||||
import { float_2, arrays_equal, get_string_width } from '../utils/helpers';
|
import { floatTwo, arraysEqual, getStringWidth } from '../utils/helpers';
|
||||||
import BaseChart from './BaseChart';
|
import BaseChart from './BaseChart';
|
||||||
|
|
||||||
export default class AxisChart extends BaseChart {
|
export default class AxisChart extends BaseChart {
|
||||||
@ -41,7 +42,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
this.x_old_axis_positions = this.x_axis_positions.slice();
|
this.x_old_axis_positions = this.x_axis_positions.slice();
|
||||||
}
|
}
|
||||||
this.x_axis_positions = this.x.map((d, i) =>
|
this.x_axis_positions = this.x.map((d, i) =>
|
||||||
float_2(this.x_offset + i * this.avg_unit_width));
|
floatTwo(this.x_offset + i * this.avg_unit_width));
|
||||||
|
|
||||||
if(!this.x_old_axis_positions) {
|
if(!this.x_old_axis_positions) {
|
||||||
this.x_old_axis_positions = this.x_axis_positions.slice();
|
this.x_old_axis_positions = this.x_axis_positions.slice();
|
||||||
@ -158,7 +159,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
this.x_axis_group.textContent = '';
|
this.x_axis_group.textContent = '';
|
||||||
this.x.map((point, i) => {
|
this.x.map((point, i) => {
|
||||||
let space_taken = get_string_width(point, char_width) + 2;
|
let space_taken = getStringWidth(point, char_width) + 2;
|
||||||
if(space_taken > allowed_space) {
|
if(space_taken > allowed_space) {
|
||||||
if(this.is_series) {
|
if(this.is_series) {
|
||||||
// Skip some axis lines if X axis is a series
|
// Skip some axis lines if X axis is a series
|
||||||
@ -301,7 +302,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
let unit_renderer = new UnitRenderer(this.height, this.zero_line, this.avg_unit_width);
|
let unit_renderer = new UnitRenderer(this.height, this.zero_line, this.avg_unit_width);
|
||||||
|
|
||||||
y_values.map((y, i) => {
|
y_values.map((y, i) => {
|
||||||
let data_unit = unit_renderer['draw_' + unit.type](
|
let data_unit = unit_renderer[unit.type](
|
||||||
x_values[i],
|
x_values[i],
|
||||||
y,
|
y,
|
||||||
unit.args,
|
unit.args,
|
||||||
@ -405,7 +406,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
|
|
||||||
this.make_new_units_for_dataset(
|
this.make_new_units_for_dataset(
|
||||||
this.x_axis_positions,
|
this.x_axis_positions,
|
||||||
this.y_sums.map( val => float_2(this.zero_line - val * this.multiplier)),
|
this.y_sums.map( val => floatTwo(this.zero_line - val * this.multiplier)),
|
||||||
'#f0f4f7',
|
'#f0f4f7',
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
@ -480,17 +481,23 @@ export default class AxisChart extends BaseChart {
|
|||||||
this.setup_x();
|
this.setup_x();
|
||||||
this.setup_y();
|
this.setup_y();
|
||||||
|
|
||||||
|
// Change in data, so calculate dependencies
|
||||||
|
this.calc_y_dependencies();
|
||||||
|
|
||||||
|
// Got the values? Now begin drawing
|
||||||
|
this.animator = new Animator(this.height, this.width, this.zero_line, this.avg_unit_width);
|
||||||
|
|
||||||
// Animate only if positions have changed
|
// Animate only if positions have changed
|
||||||
if(!arrays_equal(this.x_old_axis_positions, this.x_axis_positions)) {
|
if(!arraysEqual(this.x_old_axis_positions, this.x_axis_positions)) {
|
||||||
this.make_x_axis(true);
|
this.make_x_axis(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
if(!this.updating) this.make_x_axis();
|
if(!this.updating) this.make_x_axis();
|
||||||
}, 350);
|
}, 350);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!arrays_equal(this.y_old_axis_values, this.y_axis_values) ||
|
if(!arraysEqual(this.y_old_axis_values, this.y_axis_values) ||
|
||||||
(this.old_specific_values &&
|
(this.old_specific_values &&
|
||||||
!arrays_equal(this.old_specific_values, this.specific_values))) {
|
!arraysEqual(this.old_specific_values, this.specific_values))) {
|
||||||
|
|
||||||
this.make_y_axis(true);
|
this.make_y_axis(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@ -501,9 +508,6 @@ export default class AxisChart extends BaseChart {
|
|||||||
}, 350);
|
}, 350);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Change in data, so calculate dependencies
|
|
||||||
this.calc_y_dependencies();
|
|
||||||
|
|
||||||
this.animate_graphs();
|
this.animate_graphs();
|
||||||
|
|
||||||
// Trigger animation with the animatable elements in this.elements_to_animate
|
// Trigger animation with the animatable elements in this.elements_to_animate
|
||||||
@ -572,35 +576,18 @@ export default class AxisChart extends BaseChart {
|
|||||||
}
|
}
|
||||||
|
|
||||||
animate_path(d, i, old_x, old_y, new_x, new_y) {
|
animate_path(d, i, old_x, old_y, new_x, new_y) {
|
||||||
// Animate path
|
const newPointsList = new_y.map((y, i) => (new_x[i] + ',' + y));
|
||||||
const new_points_list = new_y.map((y, i) => (new_x[i] + ',' + y));
|
const newPathStr = newPointsList.join("L");
|
||||||
const new_path_str = new_points_list.join("L");
|
this.elements_to_animate = this.elements_to_animate
|
||||||
|
.concat(this.animator['path'](d, newPathStr));
|
||||||
const path_args = [{unit: d.path, object: d, key: 'path'}, {d:"M"+new_path_str}, 350, "easein"];
|
|
||||||
this.elements_to_animate.push(path_args);
|
|
||||||
|
|
||||||
// Animate region
|
|
||||||
if(d.region_path) {
|
|
||||||
let reg_start_pt = `0,${this.zero_line}L`;
|
|
||||||
let reg_end_pt = `L${this.width},${this.zero_line}`;
|
|
||||||
|
|
||||||
const region_args = [
|
|
||||||
{unit: d.region_path, object: d, key: 'region_path'},
|
|
||||||
{d:"M" + reg_start_pt + new_path_str + reg_end_pt},
|
|
||||||
350,
|
|
||||||
"easein"
|
|
||||||
];
|
|
||||||
this.elements_to_animate.push(region_args);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
animate_units(d, index, old_x, old_y, new_x, new_y) {
|
animate_units(d, index, old_x, old_y, new_x, new_y) {
|
||||||
let type = this.unit_args.type;
|
let type = this.unit_args.type;
|
||||||
let unit_renderer = new UnitRenderer(this.height, this.zero_line, this.avg_unit_width);
|
|
||||||
|
|
||||||
d.svg_units.map((unit, i) => {
|
d.svg_units.map((unit, i) => {
|
||||||
if(new_x[i] === undefined || new_y[i] === undefined) return;
|
if(new_x[i] === undefined || new_y[i] === undefined) return;
|
||||||
this.elements_to_animate.push(unit_renderer['animate_' + type](
|
this.elements_to_animate.push(this.animator[type](
|
||||||
{unit:unit, array:d.svg_units, index: i}, // unit, with info to replace where it came from in the data
|
{unit:unit, array:d.svg_units, index: i}, // unit, with info to replace where it came from in the data
|
||||||
new_x[i],
|
new_x[i],
|
||||||
new_y[i],
|
new_y[i],
|
||||||
@ -624,8 +611,8 @@ export default class AxisChart extends BaseChart {
|
|||||||
const last_new_y_pos = new_y[new_y.length - 1];
|
const last_new_y_pos = new_y[new_y.length - 1];
|
||||||
|
|
||||||
if(this.no_of_extra_pts >= 0) {
|
if(this.no_of_extra_pts >= 0) {
|
||||||
// First substitute current path with a squiggled one (looking the same but
|
// First substitute current path with a squiggled one
|
||||||
// having more points at end),
|
// (that looks the same but has more points at end),
|
||||||
// then animate to stretch it later to new points
|
// then animate to stretch it later to new points
|
||||||
// (new points already have more points)
|
// (new points already have more points)
|
||||||
|
|
||||||
@ -835,7 +822,7 @@ export default class AxisChart extends BaseChart {
|
|||||||
calc_y_dependencies() {
|
calc_y_dependencies() {
|
||||||
this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999);
|
this.y_min_tops = new Array(this.x_axis_positions.length).fill(9999);
|
||||||
this.y.map(d => {
|
this.y.map(d => {
|
||||||
d.y_tops = d.values.map( val => float_2(this.zero_line - val * this.multiplier));
|
d.y_tops = d.values.map( val => floatTwo(this.zero_line - val * this.multiplier));
|
||||||
d.y_tops.map( (y_top, i) => {
|
d.y_tops.map( (y_top, i) => {
|
||||||
if(y_top < this.y_min_tops[i]) {
|
if(y_top < this.y_min_tops[i]) {
|
||||||
this.y_min_tops[i] = y_top;
|
this.y_min_tops[i] = y_top;
|
||||||
|
|||||||
@ -16,7 +16,7 @@ export default class BarChart extends AxisChart {
|
|||||||
this.unit_args = {
|
this.unit_args = {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
args: {
|
args: {
|
||||||
space_width: this.avg_unit_width/2,
|
spaceWidth: this.avg_unit_width/2,
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import SvgTip from '../objects/SvgTip';
|
import SvgTip from '../objects/SvgTip';
|
||||||
import $ from '../utils/dom';
|
import $ from '../utils/dom';
|
||||||
import { makeSVGContainer, makeSVGDefs, makeSVGGroup } from '../utils/draw';
|
import { makeSVGContainer, makeSVGDefs, makeSVGGroup } from '../utils/draw';
|
||||||
import { get_string_width } from '../utils/helpers';
|
import { getStringWidth } from '../utils/helpers';
|
||||||
import { get_color, DEFAULT_COLORS } from '../utils/colors';
|
import { getColor, DEFAULT_COLORS } from '../utils/colors';
|
||||||
import Chart from '../charts';
|
import Chart from '../charts';
|
||||||
|
|
||||||
const ALL_CHART_TYPES = ['line', 'scatter', 'bar', 'percentage', 'heatmap', 'pie'];
|
const ALL_CHART_TYPES = ['line', 'scatter', 'bar', 'percentage', 'heatmap', 'pie'];
|
||||||
@ -103,7 +103,7 @@ export default class BaseChart {
|
|||||||
this.colors = DEFAULT_COLORS;
|
this.colors = DEFAULT_COLORS;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.colors = this.colors.map(color => get_color(color));
|
this.colors = this.colors.map(color => getColor(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
set_margins(height) {
|
set_margins(height) {
|
||||||
@ -161,7 +161,7 @@ export default class BaseChart {
|
|||||||
let special_values_width = 0;
|
let special_values_width = 0;
|
||||||
let char_width = 8;
|
let char_width = 8;
|
||||||
this.specific_values.map(val => {
|
this.specific_values.map(val => {
|
||||||
let str_width = get_string_width((val.title + ""), char_width);
|
let str_width = getStringWidth((val.title + ""), char_width);
|
||||||
if(str_width > special_values_width) {
|
if(str_width > special_values_width) {
|
||||||
special_values_width = str_width - 40;
|
special_values_width = str_width - 40;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
import BaseChart from './BaseChart';
|
import BaseChart from './BaseChart';
|
||||||
import { makeSVGGroup, makeHeatSquare, makeText } from '../utils/draw';
|
import { makeSVGGroup, makeHeatSquare, makeText } from '../utils/draw';
|
||||||
import { add_days, get_dd_mm_yyyy, get_weeks_between } from '../utils/date-utils';
|
import { addDays, getDdMmYyyy, getWeeksBetween } from '../utils/date-utils';
|
||||||
import { calcDistribution, getMaxCheckpoint } from '../utils/intervals';
|
import { calcDistribution, getMaxCheckpoint } from '../utils/intervals';
|
||||||
import { is_valid_color } from '../utils/colors';
|
import { isValidColor } from '../utils/colors';
|
||||||
|
|
||||||
export default class Heatmap extends BaseChart {
|
export default class Heatmap extends BaseChart {
|
||||||
constructor({
|
constructor({
|
||||||
@ -25,14 +25,14 @@ export default class Heatmap extends BaseChart {
|
|||||||
this.count_label = count_label;
|
this.count_label = count_label;
|
||||||
|
|
||||||
let today = new Date();
|
let today = new Date();
|
||||||
this.start = start || add_days(today, 365);
|
this.start = start || addDays(today, 365);
|
||||||
|
|
||||||
legend_colors = legend_colors.slice(0, 5);
|
legend_colors = legend_colors.slice(0, 5);
|
||||||
this.legend_colors = this.validate_colors(legend_colors)
|
this.legend_colors = this.validate_colors(legend_colors)
|
||||||
? legend_colors
|
? legend_colors
|
||||||
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
|
: ['#ebedf0', '#c6e48b', '#7bc96f', '#239a3b', '#196127'];
|
||||||
|
|
||||||
// Hardcoded for a fixed 5-color theme,
|
// Fixed 5-color theme,
|
||||||
// More colors are difficult to parse visually
|
// More colors are difficult to parse visually
|
||||||
this.distribution_size = 5;
|
this.distribution_size = 5;
|
||||||
|
|
||||||
@ -45,7 +45,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
|
|
||||||
let valid = 1;
|
let valid = 1;
|
||||||
colors.forEach(function(string) {
|
colors.forEach(function(string) {
|
||||||
if(!is_valid_color(string)) {
|
if(!isValidColor(string)) {
|
||||||
valid = 0;
|
valid = 0;
|
||||||
console.warn('"' + string + '" is not a valid color.');
|
console.warn('"' + string + '" is not a valid color.');
|
||||||
}
|
}
|
||||||
@ -64,12 +64,12 @@ export default class Heatmap extends BaseChart {
|
|||||||
this.first_week_start = new Date(this.start.toDateString());
|
this.first_week_start = new Date(this.start.toDateString());
|
||||||
this.last_week_start = new Date(this.today.toDateString());
|
this.last_week_start = new Date(this.today.toDateString());
|
||||||
if(this.first_week_start.getDay() !== 7) {
|
if(this.first_week_start.getDay() !== 7) {
|
||||||
add_days(this.first_week_start, (-1) * this.first_week_start.getDay());
|
addDays(this.first_week_start, (-1) * this.first_week_start.getDay());
|
||||||
}
|
}
|
||||||
if(this.last_week_start.getDay() !== 7) {
|
if(this.last_week_start.getDay() !== 7) {
|
||||||
add_days(this.last_week_start, (-1) * this.last_week_start.getDay());
|
addDays(this.last_week_start, (-1) * this.last_week_start.getDay());
|
||||||
}
|
}
|
||||||
this.no_of_cols = get_weeks_between(this.first_week_start + '', this.last_week_start + '') + 1;
|
this.no_of_cols = getWeeksBetween(this.first_week_start + '', this.last_week_start + '') + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
set_width() {
|
set_width() {
|
||||||
@ -127,7 +127,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
this.months.push(this.current_month + '');
|
this.months.push(this.current_month + '');
|
||||||
this.month_weeks[this.current_month] = 1;
|
this.month_weeks[this.current_month] = 1;
|
||||||
}
|
}
|
||||||
add_days(current_week_sunday, 7);
|
addDays(current_week_sunday, 7);
|
||||||
}
|
}
|
||||||
this.render_month_labels();
|
this.render_month_labels();
|
||||||
}
|
}
|
||||||
@ -166,7 +166,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
let x = 13 + (index + week_col_change) * 12;
|
let x = 13 + (index + week_col_change) * 12;
|
||||||
|
|
||||||
let dataAttr = {
|
let dataAttr = {
|
||||||
'data-date': get_dd_mm_yyyy(current_date),
|
'data-date': getDdMmYyyy(current_date),
|
||||||
'data-value': data_value,
|
'data-value': data_value,
|
||||||
'data-day': current_date.getDay()
|
'data-day': current_date.getDay()
|
||||||
};
|
};
|
||||||
@ -176,7 +176,7 @@ export default class Heatmap extends BaseChart {
|
|||||||
data_group.appendChild(heatSquare);
|
data_group.appendChild(heatSquare);
|
||||||
|
|
||||||
let next_date = new Date(current_date);
|
let next_date = new Date(current_date);
|
||||||
add_days(next_date, 1);
|
addDays(next_date, 1);
|
||||||
if(next_date.getTime() > today_time) break;
|
if(next_date.getTime() > today_time) break;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -85,7 +85,7 @@ export default class LineChart extends AxisChart {
|
|||||||
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.zero_line}L` + points_str + `L${this.width},${this.zero_line}`;
|
||||||
|
|
||||||
d.region_path = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
d.regionPath = makePath(pathStr, `region-fill`, 'none', `url(#${gradient_id})`);
|
||||||
this.paths_groups[i].appendChild(d.region_path);
|
this.paths_groups[i].appendChild(d.regionPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import BaseChart from './BaseChart';
|
import BaseChart from './BaseChart';
|
||||||
import $ from '../utils/dom';
|
import $ from '../utils/dom';
|
||||||
import { makePath } from '../utils/draw';
|
import { makePath } from '../utils/draw';
|
||||||
import { lighten_darken_color } from '../utils/colors';
|
import { lightenDarkenColor } from '../utils/colors';
|
||||||
import { runSVGAnimation, transform } from '../utils/animation';
|
import { runSVGAnimation, transform } from '../utils/animation';
|
||||||
const ANGLE_RATIO = Math.PI / 180;
|
const ANGLE_RATIO = Math.PI / 180;
|
||||||
const FULL_ANGLE = 360;
|
const FULL_ANGLE = 360;
|
||||||
@ -153,7 +153,7 @@ export default class PieChart extends BaseChart {
|
|||||||
const color = this.colors[i];
|
const color = this.colors[i];
|
||||||
if(flag){
|
if(flag){
|
||||||
transform(path,this.calTranslateByAngle(this.slicesProperties[i]));
|
transform(path,this.calTranslateByAngle(this.slicesProperties[i]));
|
||||||
path.style.fill = lighten_darken_color(color,50);
|
path.style.fill = lightenDarkenColor(color,50);
|
||||||
let g_off = $.offset(this.svg);
|
let g_off = $.offset(this.svg);
|
||||||
let x = e.pageX - g_off.left + 10;
|
let x = e.pageX - g_off.left + 10;
|
||||||
let y = e.pageY - g_off.top - 10;
|
let y = e.pageY - g_off.top - 10;
|
||||||
|
|||||||
@ -1,4 +1,58 @@
|
|||||||
|
import { getBarHeightAndYAttr } from './draw-utils';
|
||||||
|
|
||||||
export function getAnimXLine() {}
|
export function getAnimXLine() {}
|
||||||
|
|
||||||
export function getAnimYLine() {}
|
export function getAnimYLine() {}
|
||||||
|
|
||||||
|
export var Animator = (function() {
|
||||||
|
var Animator = function(totalHeight, totalWidth, zeroLine, avgUnitWidth) {
|
||||||
|
// constants
|
||||||
|
this.totalHeight = totalHeight;
|
||||||
|
this.totalWidth = totalWidth;
|
||||||
|
|
||||||
|
// changeables
|
||||||
|
this.avgUnitWidth = avgUnitWidth;
|
||||||
|
this.zeroLine = zeroLine;
|
||||||
|
};
|
||||||
|
|
||||||
|
Animator.prototype = {
|
||||||
|
bar: function(barObj, x, yTop, index, noOfDatasets) {
|
||||||
|
let start = x - this.avgUnitWidth/4;
|
||||||
|
let width = (this.avgUnitWidth/2)/noOfDatasets;
|
||||||
|
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
||||||
|
|
||||||
|
x = start + (width * index);
|
||||||
|
|
||||||
|
return [barObj, {width: width, height: height, x: x, y: y}, 350, "easein"];
|
||||||
|
// bar.animate({height: args.newHeight, y: yTop}, 350, mina.easein);
|
||||||
|
},
|
||||||
|
|
||||||
|
dot: function(dotObj, x, yTop) {
|
||||||
|
return [dotObj, {cx: x, cy: yTop}, 350, "easein"];
|
||||||
|
// dot.animate({cy: yTop}, 350, mina.easein);
|
||||||
|
},
|
||||||
|
|
||||||
|
path: function(d, pathStr) {
|
||||||
|
let pathComponents = [];
|
||||||
|
const animPath = [{unit: d.path, object: d, key: 'path'}, {d:"M"+pathStr}, 350, "easein"];
|
||||||
|
pathComponents.push(animPath);
|
||||||
|
|
||||||
|
if(d.regionPath) {
|
||||||
|
let regStartPt = `0,${this.zeroLine}L`;
|
||||||
|
let regEndPt = `L${this.totalWidth}, ${this.zeroLine}`;
|
||||||
|
|
||||||
|
const animRegion = [
|
||||||
|
{unit: d.regionPath, object: d, key: 'regionPath'},
|
||||||
|
{d:"M" + regStartPt + pathStr + regEndPt},
|
||||||
|
350,
|
||||||
|
"easein"
|
||||||
|
];
|
||||||
|
pathComponents.push(animRegion);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pathComponents;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
return Animator;
|
||||||
|
})();
|
||||||
|
|||||||
@ -9,52 +9,52 @@ const EASING = {
|
|||||||
easeinout: "0.42 0 0.58 1"
|
easeinout: "0.42 0 0.58 1"
|
||||||
};
|
};
|
||||||
|
|
||||||
function animateSVG(element, props, dur, easing_type="linear", type=undefined, old_values={}) {
|
function animateSVG(element, props, dur, easingType="linear", type=undefined, oldValues={}) {
|
||||||
|
|
||||||
let anim_element = element.cloneNode(true);
|
let animElement = element.cloneNode(true);
|
||||||
let new_element = element.cloneNode(true);
|
let newElement = element.cloneNode(true);
|
||||||
|
|
||||||
for(var attributeName in props) {
|
for(var attributeName in props) {
|
||||||
let animate_element;
|
let animateElement;
|
||||||
if(attributeName === 'transform') {
|
if(attributeName === 'transform') {
|
||||||
animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
|
animateElement = document.createElementNS("http://www.w3.org/2000/svg", "animateTransform");
|
||||||
} else {
|
} else {
|
||||||
animate_element = document.createElementNS("http://www.w3.org/2000/svg", "animate");
|
animateElement = document.createElementNS("http://www.w3.org/2000/svg", "animate");
|
||||||
}
|
}
|
||||||
let current_value = old_values[attributeName] || element.getAttribute(attributeName);
|
let currentValue = oldValues[attributeName] || element.getAttribute(attributeName);
|
||||||
let value = props[attributeName];
|
let value = props[attributeName];
|
||||||
|
|
||||||
let anim_attr = {
|
let animAttr = {
|
||||||
attributeName: attributeName,
|
attributeName: attributeName,
|
||||||
from: current_value,
|
from: currentValue,
|
||||||
to: value,
|
to: value,
|
||||||
begin: "0s",
|
begin: "0s",
|
||||||
dur: dur/1000 + "s",
|
dur: dur/1000 + "s",
|
||||||
values: current_value + ";" + value,
|
values: currentValue + ";" + value,
|
||||||
keySplines: EASING[easing_type],
|
keySplines: EASING[easingType],
|
||||||
keyTimes: "0;1",
|
keyTimes: "0;1",
|
||||||
calcMode: "spline",
|
calcMode: "spline",
|
||||||
fill: 'freeze'
|
fill: 'freeze'
|
||||||
};
|
};
|
||||||
|
|
||||||
if(type) {
|
if(type) {
|
||||||
anim_attr["type"] = type;
|
animAttr["type"] = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var i in anim_attr) {
|
for (var i in animAttr) {
|
||||||
animate_element.setAttribute(i, anim_attr[i]);
|
animateElement.setAttribute(i, animAttr[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
anim_element.appendChild(animate_element);
|
animElement.appendChild(animateElement);
|
||||||
|
|
||||||
if(type) {
|
if(type) {
|
||||||
new_element.setAttribute(attributeName, `translate(${value})`);
|
newElement.setAttribute(attributeName, `translate(${value})`);
|
||||||
} else {
|
} else {
|
||||||
new_element.setAttribute(attributeName, value);
|
newElement.setAttribute(attributeName, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return [anim_element, new_element];
|
return [animElement, newElement];
|
||||||
}
|
}
|
||||||
|
|
||||||
export function transform(element, style) { // eslint-disable-line no-unused-vars
|
export function transform(element, style) { // eslint-disable-line no-unused-vars
|
||||||
@ -65,37 +65,37 @@ export function transform(element, style) { // eslint-disable-line no-unused-var
|
|||||||
element.style.oTransform = style;
|
element.style.oTransform = style;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function runSVGAnimation(svg_container, elements) {
|
export function runSVGAnimation(svgContainer, elements) {
|
||||||
let new_elements = [];
|
let newElements = [];
|
||||||
let anim_elements = [];
|
let animElements = [];
|
||||||
|
|
||||||
elements.map(element => {
|
elements.map(element => {
|
||||||
let obj = element[0];
|
let obj = element[0];
|
||||||
let parent = obj.unit.parentNode;
|
let parent = obj.unit.parentNode;
|
||||||
|
|
||||||
let anim_element, new_element;
|
let animElement, newElement;
|
||||||
|
|
||||||
element[0] = obj.unit;
|
element[0] = obj.unit;
|
||||||
[anim_element, new_element] = animateSVG(...element);
|
[animElement, newElement] = animateSVG(...element);
|
||||||
|
|
||||||
new_elements.push(new_element);
|
newElements.push(newElement);
|
||||||
anim_elements.push([anim_element, parent]);
|
animElements.push([animElement, parent]);
|
||||||
|
|
||||||
parent.replaceChild(anim_element, obj.unit);
|
parent.replaceChild(animElement, obj.unit);
|
||||||
|
|
||||||
if(obj.array) {
|
if(obj.array) {
|
||||||
obj.array[obj.index] = new_element;
|
obj.array[obj.index] = newElement;
|
||||||
} else {
|
} else {
|
||||||
obj.object[obj.key] = new_element;
|
obj.object[obj.key] = newElement;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let anim_svg = svg_container.cloneNode(true);
|
let animSvg = svgContainer.cloneNode(true);
|
||||||
|
|
||||||
anim_elements.map((anim_element, i) => {
|
animElements.map((animElement, i) => {
|
||||||
anim_element[1].replaceChild(new_elements[i], anim_element[0]);
|
animElement[1].replaceChild(newElements[i], animElement[0]);
|
||||||
elements[i][0] = new_elements[i];
|
elements[i][0] = newElements[i];
|
||||||
});
|
});
|
||||||
|
|
||||||
return anim_svg;
|
return animSvg;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,31 +18,31 @@ const PRESET_COLOR_MAP = {
|
|||||||
export const DEFAULT_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
|
export const DEFAULT_COLORS = ['light-blue', 'blue', 'violet', 'red', 'orange',
|
||||||
'yellow', 'green', 'light-green', 'purple', 'magenta'];
|
'yellow', 'green', 'light-green', 'purple', 'magenta'];
|
||||||
|
|
||||||
function limit_color(r){
|
function limitColor(r){
|
||||||
if (r > 255) return 255;
|
if (r > 255) return 255;
|
||||||
else if (r < 0) return 0;
|
else if (r < 0) return 0;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function lighten_darken_color(color, amt) {
|
export function lightenDarkenColor(color, amt) {
|
||||||
let col = get_color(color);
|
let col = getColor(color);
|
||||||
let usePound = false;
|
let usePound = false;
|
||||||
if (col[0] == "#") {
|
if (col[0] == "#") {
|
||||||
col = col.slice(1);
|
col = col.slice(1);
|
||||||
usePound = true;
|
usePound = true;
|
||||||
}
|
}
|
||||||
let num = parseInt(col,16);
|
let num = parseInt(col,16);
|
||||||
let r = limit_color((num >> 16) + amt);
|
let r = limitColor((num >> 16) + amt);
|
||||||
let b = limit_color(((num >> 8) & 0x00FF) + amt);
|
let b = limitColor(((num >> 8) & 0x00FF) + amt);
|
||||||
let g = limit_color((num & 0x0000FF) + amt);
|
let g = limitColor((num & 0x0000FF) + amt);
|
||||||
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
|
return (usePound?"#":"") + (g | (b << 8) | (r << 16)).toString(16);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function is_valid_color(string) {
|
export function isValidColor(string) {
|
||||||
// https://stackoverflow.com/a/8027444/6495043
|
// https://stackoverflow.com/a/8027444/6495043
|
||||||
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(string);
|
return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(string);
|
||||||
}
|
}
|
||||||
|
|
||||||
export const get_color = (color) => {
|
export const getColor = (color) => {
|
||||||
return PRESET_COLOR_MAP[color] || color;
|
return PRESET_COLOR_MAP[color] || color;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,13 +1,13 @@
|
|||||||
// Playing around with dates
|
// Playing around with dates
|
||||||
|
|
||||||
// https://stackoverflow.com/a/11252167/6495043
|
// https://stackoverflow.com/a/11252167/6495043
|
||||||
function treat_as_utc(date_str) {
|
function treatAsUtc(dateStr) {
|
||||||
let result = new Date(date_str);
|
let result = new Date(dateStr);
|
||||||
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
result.setMinutes(result.getMinutes() - result.getTimezoneOffset());
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_dd_mm_yyyy(date) {
|
export function getDdMmYyyy(date) {
|
||||||
let dd = date.getDate();
|
let dd = date.getDate();
|
||||||
let mm = date.getMonth() + 1; // getMonth() is zero-based
|
let mm = date.getMonth() + 1; // getMonth() is zero-based
|
||||||
return [
|
return [
|
||||||
@ -17,18 +17,18 @@ export function get_dd_mm_yyyy(date) {
|
|||||||
].join('-');
|
].join('-');
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_weeks_between(start_date_str, end_date_str) {
|
export function getWeeksBetween(startDateStr, endDateStr) {
|
||||||
return Math.ceil(get_days_between(start_date_str, end_date_str) / 7);
|
return Math.ceil(getDaysBetween(startDateStr, endDateStr) / 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_days_between(start_date_str, end_date_str) {
|
export function getDaysBetween(startDateStr, endDateStr) {
|
||||||
let milliseconds_per_day = 24 * 60 * 60 * 1000;
|
let millisecondsPerDay = 24 * 60 * 60 * 1000;
|
||||||
return (treat_as_utc(end_date_str) - treat_as_utc(start_date_str)) / milliseconds_per_day;
|
return (treatAsUtc(endDateStr) - treatAsUtc(startDateStr)) / millisecondsPerDay;
|
||||||
}
|
}
|
||||||
|
|
||||||
// mutates
|
// mutates
|
||||||
export function add_days(date, number_of_days) {
|
export function addDays(date, numberOfDays) {
|
||||||
date.setDate(date.getDate() + number_of_days);
|
date.setDate(date.getDate() + numberOfDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
// export function get_month_name() {}
|
// export function getMonthName() {}
|
||||||
|
|||||||
23
src/scripts/utils/draw-utils.js
Normal file
23
src/scripts/utils/draw-utils.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
export function getBarHeightAndYAttr(yTop, zeroLine, totalHeight) {
|
||||||
|
let height, y;
|
||||||
|
if (yTop <= zeroLine) {
|
||||||
|
height = zeroLine - yTop;
|
||||||
|
y = yTop;
|
||||||
|
|
||||||
|
// In case of invisible bars
|
||||||
|
if(height === 0) {
|
||||||
|
height = totalHeight * 0.01;
|
||||||
|
y -= height;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
height = yTop - zeroLine;
|
||||||
|
y = zeroLine;
|
||||||
|
|
||||||
|
// In case of invisible bars
|
||||||
|
if(height === 0) {
|
||||||
|
height = totalHeight * 0.01;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [height, y];
|
||||||
|
}
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { getBarHeightAndYAttr } from './draw-utils';
|
||||||
|
|
||||||
// Constants used
|
// Constants used
|
||||||
|
|
||||||
function $(expr, con) {
|
function $(expr, con) {
|
||||||
@ -49,7 +51,7 @@ function renderVerticalGradient(svgDefElem, gradientId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setGradientStop(gradElem, offset, color, opacity) {
|
function setGradientStop(gradElem, offset, color, opacity) {
|
||||||
createSVG('stop', {
|
return createSVG('stop', {
|
||||||
'inside': gradElem,
|
'inside': gradElem,
|
||||||
'style': `stop-color: ${color}`,
|
'style': `stop-color: ${color}`,
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
@ -194,58 +196,34 @@ export function makeYLine(startAt, width, textEndAt, point, labelClass, axisLine
|
|||||||
}
|
}
|
||||||
|
|
||||||
export var UnitRenderer = (function() {
|
export var UnitRenderer = (function() {
|
||||||
var UnitRenderer = function(total_height, zero_line, avg_unit_width) {
|
var UnitRenderer = function(totalHeight, zeroLine, avgUnitWidth) {
|
||||||
this.total_height = total_height;
|
this.totalHeight = totalHeight;
|
||||||
this.zero_line = zero_line;
|
this.zeroLine = zeroLine;
|
||||||
this.avg_unit_width = avg_unit_width;
|
this.avgUnitWidth = avgUnitWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
function get_bar_height_and_y_attr(y_top, zero_line, total_height) {
|
|
||||||
let height, y;
|
|
||||||
if (y_top <= zero_line) {
|
|
||||||
height = zero_line - y_top;
|
|
||||||
y = y_top;
|
|
||||||
|
|
||||||
// In case of invisible bars
|
|
||||||
if(height === 0) {
|
|
||||||
height = total_height * 0.01;
|
|
||||||
y -= height;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
height = y_top - zero_line;
|
|
||||||
y = zero_line;
|
|
||||||
|
|
||||||
// In case of invisible bars
|
|
||||||
if(height === 0) {
|
|
||||||
height = total_height * 0.01;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return [height, y];
|
|
||||||
}
|
|
||||||
|
|
||||||
UnitRenderer.prototype = {
|
UnitRenderer.prototype = {
|
||||||
draw_bar: function (x, y_top, args, color, index, dataset_index, no_of_datasets) {
|
bar: function (x, yTop, args, color, index, datasetIndex, noOfDatasets) {
|
||||||
let total_width = this.avg_unit_width - args.space_width;
|
let totalWidth = this.avgUnitWidth - args.spaceWidth;
|
||||||
let start_x = x - total_width/2;
|
let startX = x - totalWidth/2;
|
||||||
|
|
||||||
let width = total_width / no_of_datasets;
|
let width = totalWidth / noOfDatasets;
|
||||||
let current_x = start_x + width * dataset_index;
|
let currentX = startX + width * datasetIndex;
|
||||||
|
|
||||||
let [height, y] = get_bar_height_and_y_attr(y_top, this.zero_line, this.total_height);
|
let [height, y] = getBarHeightAndYAttr(yTop, this.zeroLine, this.totalHeight);
|
||||||
|
|
||||||
return createSVG('rect', {
|
return createSVG('rect', {
|
||||||
className: `bar mini`,
|
className: `bar mini`,
|
||||||
style: `fill: ${color}`,
|
style: `fill: ${color}`,
|
||||||
'data-point-index': index,
|
'data-point-index': index,
|
||||||
x: current_x,
|
x: currentX,
|
||||||
y: y,
|
y: y,
|
||||||
width: width,
|
width: width,
|
||||||
height: height
|
height: height
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
draw_dot: function(x, y, args, color, index) {
|
dot: function(x, y, args, color, index) {
|
||||||
return createSVG('circle', {
|
return createSVG('circle', {
|
||||||
style: `fill: ${color}`,
|
style: `fill: ${color}`,
|
||||||
'data-point-index': index,
|
'data-point-index': index,
|
||||||
@ -253,22 +231,6 @@ export var UnitRenderer = (function() {
|
|||||||
cy: y,
|
cy: y,
|
||||||
r: args.radius
|
r: args.radius
|
||||||
});
|
});
|
||||||
},
|
|
||||||
|
|
||||||
animate_bar: function(bar_obj, x, y_top, index, no_of_datasets) {
|
|
||||||
let start = x - this.avg_unit_width/4;
|
|
||||||
let width = (this.avg_unit_width/2)/no_of_datasets;
|
|
||||||
let [height, y] = get_bar_height_and_y_attr(y_top, this.zero_line, this.total_height);
|
|
||||||
|
|
||||||
x = start + (width * index);
|
|
||||||
|
|
||||||
return [bar_obj, {width: width, height: height, x: x, y: y}, 350, "easein"];
|
|
||||||
// bar.animate({height: args.new_height, y: y_top}, 350, mina.easein);
|
|
||||||
},
|
|
||||||
|
|
||||||
animate_dot: function(dot_obj, x, y_top) {
|
|
||||||
return [dot_obj, {cx: x, cy: y_top}, 350, "easein"];
|
|
||||||
// dot.animate({cy: y_top}, 350, mina.easein);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
* Returns the value of a number upto 2 decimal places.
|
* Returns the value of a number upto 2 decimal places.
|
||||||
* @param {Number} d Any number
|
* @param {Number} d Any number
|
||||||
*/
|
*/
|
||||||
export function float_2(d) {
|
export function floatTwo(d) {
|
||||||
return parseFloat(d.toFixed(2));
|
return parseFloat(d.toFixed(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -11,13 +11,13 @@ export function float_2(d) {
|
|||||||
* @param {Array} arr1 First array
|
* @param {Array} arr1 First array
|
||||||
* @param {Array} arr2 Second array
|
* @param {Array} arr2 Second array
|
||||||
*/
|
*/
|
||||||
export function arrays_equal(arr1, arr2) {
|
export function arraysEqual(arr1, arr2) {
|
||||||
if(arr1.length !== arr2.length) return false;
|
if(arr1.length !== arr2.length) return false;
|
||||||
let are_equal = true;
|
let areEqual = true;
|
||||||
arr1.map((d, i) => {
|
arr1.map((d, i) => {
|
||||||
if(arr2[i] !== d) are_equal = false;
|
if(arr2[i] !== d) areEqual = false;
|
||||||
});
|
});
|
||||||
return are_equal;
|
return areEqual;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -40,8 +40,8 @@ export function shuffle(array) {
|
|||||||
/**
|
/**
|
||||||
* Returns pixel width of string.
|
* Returns pixel width of string.
|
||||||
* @param {String} string
|
* @param {String} string
|
||||||
* @param {Number} char_width Width of single char in pixels
|
* @param {Number} charWidth Width of single char in pixels
|
||||||
*/
|
*/
|
||||||
export function get_string_width(string, char_width) {
|
export function getStringWidth(string, charWidth) {
|
||||||
return (string+"").length * char_width;
|
return (string+"").length * charWidth;
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user