transcend-charts
Version:
Transcend is a charting and graph library for NUVI
781 lines (693 loc) • 28.6 kB
JavaScript
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _lodash = require('lodash');
var _lodash2 = _interopRequireDefault(_lodash);
var _Numbers = require('../helpers/Numbers');
var _Numbers2 = _interopRequireDefault(_Numbers);
var _Charts = require('../helpers/Charts');
var _Charts2 = _interopRequireDefault(_Charts);
var _Color = require('./Color');
var _Color2 = _interopRequireDefault(_Color);
var _ChartDictionary = require('./ChartDictionary');
var _ChartDictionary2 = _interopRequireDefault(_ChartDictionary);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
var PieChart = function PieChart(htmlContainer, graphData, graphOptions) {
var self = this;
var htmlCanvas = null;
var needsRender = false;
var data = null;
var plotVars = {
graphArea: { top: 0, right: 0, bottom: 0, left: 0, width: 0, height: 0 } }; // this var is updated regularly in the render function to ensure it always contains correct data about the size and state of the graph
var DEBUG = false;
var fullScreenChangeListener;
var webkitFullScreenChangeListener;
var mozFullScreenChangeListener;
var msFullScreenChangeListener;
var resizeListener;
var isDestroyed = false;
var resizeTimer = null;
var options = graphOptions;
// background and padding
if (!options.backgroundColor) {
options.backgroundColor = new _Color2.default.Color('transparent');
} else {
options.backgroundColor = new _Color2.default.Color(options.backgroundColor);
}
if (!options.padding) {
options.padding = 0;
} else {
options.padding = parseFloat(options.padding);
}
// bar styles
if (!options.fillColor) {
options.fillColor = new _Color2.default.Color('#888888');
} else {
options.fillColor = new _Color2.default.Color(options.fillColor);
}
if (!options.borderColor) {
options.borderColor = new _Color2.default.Color('transparent');
} else {
options.borderColor = new _Color2.default.Color(options.borderColor);
}
if (!options.borderWidth) {
options.borderWidth = 0;
} else {
options.borderWidth = parseFloat(options.borderWidth);
}
// labels on the bars
if (options.labelPosition !== 'bottom') {
options.labelPosition = 'above';
}
if (!options.labelFontSize) {
//options.labelFontSize = 12;
options.labelFontSizeAsPct = 0.33;
} else if (typeof options.labelFontSize === 'string' && options.labelFontSize.indexOf('%') !== -1) {
options.labelFontSizeAsPct = parseFloat(options.labelFontSize) / 100;
} else {
options.labelFontSize = parseFloat(options.labelFontSize);
options.labelFontSizeAsPct = null;
}
if (!options.labelFontColor) {
options.labelFontColor = options.gridFontColor;
} else {
options.labelFontColor = new _Color2.default.Color(options.labelFontColor);
}
if (!options.labelFontFamily) {
options.labelFontFamily = 'Arial';
}
if (!options.labelFontWeight) {
options.labelFontWeight = '400';
}
// values floating on top of each bar
if (options.showValues === undefined || options.showValues === false) {
options.showValues = false;
} else {
options.showValues = true;
}
if (!options.valueFontColor) {
options.valueFontColor = options.gridFontColor;
}
if (!options.valueFontSize) {
//options.valueFontSize = 50;
options.valueFontSizeAsPct = 0.66;
} else if (typeof options.valueFontSize === 'string' && options.valueFontSize.indexOf('%') !== -1) {
options.valueFontSizeAsPct = parseFloat(options.valueFontSize) / 100;
} else {
options.valueFontSize = parseFloat(options.valueFontSize);
options.valueFontSizeAsPct = null;
}
if (!options.valueFontFamily) {
options.valueFontFamily = 'Arial';
}
if (!options.valueFontWeight) {
options.valueFontWeight = '400';
}
if (!options.stripeWidth) {
options.stripeWidth = 0;
} else {
options.stripeWidth = parseFloat(options.stripeWidth);
}
if (!options.stripeSpacing) {
options.stripeSpacing = 10;
} else {
options.stripeSpacing = parseFloat(options.stripeSpacing);
}
if (!options.stripeColor) {
options.stripeColor = new _Color2.default.Color('#ffffff');
} else {
options.stripeColor = new _Color2.default.Color(options.stripeColor);
}
// show legend
if (options.showLegend === undefined || options.showLegend === null || options.showLegend === true) {
options.showLegend = true;
} else {
options.showLegend = false;
}
if (!options.legendFontSize) {
options.legendFontSize = 24;
} else {
options.legendFontSize = parseFloat(options.legendFontSize);
}
if (!options.legendFontFamily) {
options.legendFontFamily = 'Arial';
}
if (!options.legendFontWeight) {
options.legendFontWeight = '400';
}
if (!options.legendFontColor) {
options.legendFontColor = new _Color2.default.Color('#ffffff');
} else {
options.legendFontColor = new _Color2.default.Color(options.legendFontColor);
}
if (!options.legendPadding) {
options.legendPadding = 0;
} else {
options.legendPadding = parseFloat(options.legendPadding);
}
if (!options.legendBackgroundColor) {
options.legendBackgroundColor = new _Color2.default.Color('transparent');
} else {
options.legendBackgroundColor = new _Color2.default.Color(options.legendBackgroundColor);
}
if (!options.knockoutCenterColor) {
options.knockoutCenterColor = new _Color2.default.Color('rgba(47, 47, 47, 1)');
} else {
options.knockoutCenterColor = new _Color2.default.Color(options.knockoutCenterColor);
}
if (!options.knockoutOuterColor) {
options.knockoutOuterColor = new _Color2.default.Color('rgba(47, 47, 47, 0.85)');
} else {
options.knockoutOuterColor = new _Color2.default.Color(options.knockoutOuterColor);
}
var pxRatio = window.devicePixelRatio || 1;
var knockoutCircleRadiusAsPct = 0.75;
var valueSizeAsPctOfKnockoutDiameter = 0.75;
var legendLabelValueSpacing = 10;
var legendSpacing = 20;
var legendLineHeight = 1.75;
this.render = function (exportAsImage, scale) {
if (!data) {
return false;
}
var canvas = htmlCanvas;
var ctx = canvas.getContext('2d');
if (!scale) {
scale = 1;
}
var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
if (exportAsImage) {
canvas = document.createElement('CANVAS');
canvas.width = htmlCanvas.width * scale;
canvas.height = htmlCanvas.height * scale;
ctx = canvas.getContext('2d');
}
// upscale this thang if the device pixel ratio is higher than 1
ctx.save();
if (pxRatio > 1 || scale !== 1) {
ctx.scale(pxRatio / backingStoreRatio * scale, pxRatio / backingStoreRatio * scale);
}
var canvasWidth = canvas.width / (pxRatio / backingStoreRatio * scale);
var canvasHeight = canvas.height / (pxRatio / backingStoreRatio * scale);
// fill background
ctx.clearRect(0, 0, canvasWidth, canvasHeight);
if (options.backgroundColor.getRgba() !== 'transparent') {
ctx.fillStyle = options.backgroundColor.getRgba();
ctx.fillRect(0, 0, canvasWidth, canvasHeight);
}
// calculate the total of all values
var totalValue = _lodash2.default.sum(data, function (datum) {
return datum.value;
});
// calculate the widest value
ctx.font = options.legendFontWeight + ' ' + options.legendFontSize + 'px ' + options.legendFontFamily;
var datumWithWidestValue = _lodash2.default.max(data, function (datum) {
var displayValue = datum.prefix + datum.value + datum.suffix;
if (datum.displayValue) {
displayValue = datum.displayValue;
}
return ctx.measureText(displayValue).width;
});
var displayValue = datumWithWidestValue.prefix + datumWithWidestValue.value + datumWithWidestValue.suffix;
if (datumWithWidestValue.displayValue) {
displayValue = datumWithWidestValue.displayValue;
}
var datumWithWidestValueWidth = ctx.measureText(displayValue).width;
// calculate the widest label
var datumWithWidestLabel = _lodash2.default.max(data, function (datum) {
return ctx.measureText(datum.name).width;
});
var datumWithWidestLabelWidth = ctx.measureText(datumWithWidestLabel.name).width;
// calculate grid area
plotVars.graphArea = {
left: options.padding,
top: options.padding,
right: options.padding,
bottom: options.padding
};
plotVars.graphArea.width = canvasWidth - plotVars.graphArea.left - plotVars.graphArea.right;
plotVars.graphArea.height = canvasHeight - plotVars.graphArea.top - plotVars.graphArea.bottom;
// set up a legend area
if (options.showLegend) {
// determine the size of the legend
var legendHeight = data.length * (options.legendFontSize * legendLineHeight) + options.legendPadding * 2;
var legendWidth = datumWithWidestLabelWidth + legendLabelValueSpacing + datumWithWidestValueWidth + options.legendPadding * 2;
// determine the position of the legendArea
plotVars.legendArea = {
top: (canvasHeight - legendHeight) / 2,
right: options.padding,
bottom: (canvasHeight - legendHeight) / 2,
left: canvasWidth - (options.padding + legendWidth)
};
plotVars.legendArea.width = canvasWidth - plotVars.legendArea.right - plotVars.legendArea.left;
plotVars.legendArea.height = canvasHeight - plotVars.legendArea.bottom - plotVars.legendArea.top;
// determine the position of the graphArea
plotVars.graphArea.right = options.padding + legendWidth + legendSpacing;
plotVars.graphArea.width = canvasWidth - plotVars.graphArea.left - plotVars.graphArea.right;
if (plotVars.graphArea.width > plotVars.graphArea.height) {
var extraWidth = plotVars.graphArea.width - plotVars.graphArea.height;
plotVars.graphArea.left += extraWidth / 2;
plotVars.graphArea.right += extraWidth / 2;
plotVars.legendArea.left -= extraWidth / 2;
plotVars.legendArea.right -= extraWidth / 2;
}
ctx.fillStyle = options.legendBackgroundColor.toString();
ctx.fillRect(plotVars.legendArea.left, plotVars.legendArea.top, plotVars.legendArea.width, plotVars.legendArea.height);
ctx.textAlign = 'left';
ctx.textBaseline = 'bottom';
for (var i = 0; i < data.length; i++) {
var displayValue = data[i].prefix + data[i].value + data[i].suffix;
if (data[i].displayValue) {
displayValue = data[i].displayValue;
}
ctx.fillStyle = options.legendFontColor.toString();
ctx.fillText(data[i].name, plotVars.legendArea.left + options.legendPadding, plotVars.legendArea.top + (i + 1) * options.legendFontSize * legendLineHeight);
ctx.fillStyle = data[i].fillColor.toString();
ctx.fillText(displayValue, plotVars.legendArea.left + options.legendPadding + datumWithWidestLabelWidth + legendLabelValueSpacing, plotVars.legendArea.top + (i + 1) * options.legendFontSize * legendLineHeight);
data[i].boundingBox = {
x: plotVars.legendArea.left + options.legendPadding,
width: datumWithWidestLabelWidth + legendLabelValueSpacing + datumWithWidestValueWidth,
y: plotVars.legendArea.top + i * options.legendFontSize * legendLineHeight,
height: options.legendFontSize * legendLineHeight
};
}
}
// determine the radius of the stinking pie chart
var pieRadius = plotVars.graphArea.height / 2;
if (plotVars.graphArea.width < plotVars.graphArea.height) {
pieRadius = plotVars.graphArea.width / 2;
}
if (pieRadius < 0) {
pieRadius = 1;
}
// let's set a var for the center of the pie
var pieCenter = {
x: plotVars.graphArea.left + (canvasWidth - plotVars.graphArea.left - plotVars.graphArea.right) / 2,
y: plotVars.graphArea.top + (canvasHeight - plotVars.graphArea.top - plotVars.graphArea.bottom) / 2
};
// determine now whether something is highlighted or not
var somethingIsHighlighted = false;
for (var i = 0; i < data.length; i++) {
if (data[i].isHighlighted) {
somethingIsHighlighted = true;
break;
}
}
// render the blasted pie slices
var movingRadian = -Math.PI / 2;
for (var i = 0; i < data.length; i++) {
var percent = data[i].value / totalValue;
var fillColor = new _Color2.default.Color(data[i].fillColor);
if (somethingIsHighlighted && !data[i].isHighlighted) {
fillColor.fade(0.7);
}
ctx.fillStyle = fillColor.toString();
var strokeColor = new _Color2.default.Color(data[i].borderColor);
ctx.strokeStyle = strokeColor.toString();
ctx.lineWidth = options.borderWidth;
ctx.beginPath();
ctx.moveTo(pieCenter.x, pieCenter.y);
ctx.lineTo(pieCenter.x + Math.cos(movingRadian) * pieRadius, pieCenter.y + Math.sin(movingRadian) * pieRadius);
ctx.arc(pieCenter.x, pieCenter.y, pieRadius, movingRadian, movingRadian + percent * Math.PI * 2);
ctx.lineTo(pieCenter.x, pieCenter.y);
ctx.fill();
ctx.stroke();
if (options.stripeWidth && (!somethingIsHighlighted || data[i].isHighlighted)) {
ctx.save();
ctx.clip();
ctx.lineWidth = options.stripeWidth;
ctx.strokeStyle = options.stripeColor.toString();
ctx.beginPath();
for (var x = pieCenter.x - pieRadius - pieRadius * 2; x < pieCenter.x + pieRadius; x += options.stripeSpacing) {
ctx.moveTo(x, pieCenter.y + pieRadius);
ctx.lineTo(x + pieRadius * 2, pieCenter.y - pieRadius);
}
ctx.stroke();
ctx.restore();
}
movingRadian += percent * Math.PI * 2;
}
// render the knockout with the percentage on top
var fillGradient = ctx.createRadialGradient(pieCenter.x, pieCenter.y, 0, pieCenter.x, pieCenter.y, pieRadius * knockoutCircleRadiusAsPct);
fillGradient.addColorStop(0.55, options.knockoutCenterColor);
fillGradient.addColorStop(1, options.knockoutOuterColor);
ctx.fillStyle = fillGradient;
ctx.beginPath();
ctx.arc(pieCenter.x, pieCenter.y, pieRadius * knockoutCircleRadiusAsPct, 0, Math.PI * 2);
ctx.fill();
if (somethingIsHighlighted) {
// find the font size that makes the widest value fit in the knockout circle
var highlightedValueFontSize = Math.floor(pieRadius * 2 * knockoutCircleRadiusAsPct);
while (true) {
var displayValue = datumWithWidestValue.prefix + datumWithWidestValue.value + datumWithWidestValue.suffix;
if (datumWithWidestValue.displayValue) {
displayValue = datumWithWidestValue.displayValue;
}
ctx.font = options.valueFontWeight + ' ' + highlightedValueFontSize + 'px ' + options.valueFontFamily;
if (ctx.measureText(displayValue).width < pieRadius * 2 * knockoutCircleRadiusAsPct * valueSizeAsPctOfKnockoutDiameter) {
break;
}
highlightedValueFontSize = Math.floor(highlightedValueFontSize * 0.9);
}
var highlightedLabelFontSize = Math.floor(pieRadius * 2 * knockoutCircleRadiusAsPct);
while (true) {
ctx.font = options.labelFontWeight + ' ' + highlightedLabelFontSize + 'px ' + options.labelFontFamily;
if (ctx.measureText(datumWithWidestLabel.name).width < pieRadius * 2 * knockoutCircleRadiusAsPct * valueSizeAsPctOfKnockoutDiameter) {
break;
}
highlightedLabelFontSize = Math.floor(highlightedLabelFontSize * 0.9);
}
highlightedLabelFontSize = _lodash2.default.min([highlightedLabelFontSize, options.labelFontSize]);
// render the highlighted part if any
for (var i = 0; i < data.length; i++) {
if (data[i].isHighlighted) {
var displayValue = data[i].prefix + data[i].value + data[i].suffix;
if (data[i].displayValue) {
displayValue = data[i].displayValue;
}
ctx.font = options.valueFontWeight + ' ' + highlightedValueFontSize + 'px ' + options.valueFontFamily;
ctx.textAlign = 'center';
ctx.textBaseline = 'alphabetic';
ctx.fillStyle = data[i].fillColor.toString();
ctx.fillText(displayValue, pieCenter.x, pieCenter.y);
ctx.textBaseline = 'top';
ctx.fillStyle = options.labelFontColor.toString();
ctx.font = options.labelFontWeight + ' ' + highlightedLabelFontSize + 'px ' + options.labelFontFamily;
ctx.fillText(data[i].name, pieCenter.x, pieCenter.y);
}
}
}
// draw fps
if (DEBUG) {
ctx.fillStyle = '#666666';
ctx.fillRect(canvasWidth - 40, canvasHeight - 15, 40, 15);
ctx.textAlign = 'right';
ctx.textBaseline = 'bottom';
ctx.fillStyle = '#000000';
ctx.font = '11px sans-serif';
ctx.fillText(String(Math.round(fps)) + ' fps', canvasWidth - 5, canvasHeight - 1);
}
ctx.restore();
if (exportAsImage) {
return canvas.toDataURL('image/png');
}
};
/***
* This publicly exposed method can be used to highlight a pie slice from outside of the class
***/
this.highlightPieSlice = function (dataSliceName) {
for (var i = 0; i < data.length; i++) {
if (data[i].name === dataSliceName) {
data[i].isHighlighted = true;
} else {
data[i].isHighlighted = false;
}
}
};
this.getBase64Image = function (scale) {
// call render with a special flag
return this.render(true, scale);
};
/***
* Initialize some basic vars including the html canvas to render on
***/
function _init() {
var _this = this;
htmlCanvas = document.createElement('CANVAS');
htmlContainer.appendChild(htmlCanvas);
self.setData(graphData);
setTimeout(fillParent, 1);
resizeListener = window.addEventListener('resize', function () {
clearTimeout(resizeTimer);
resizeTimer = setTimeout(function () {
fillParent.call(_this);
}, 50);
});
fullScreenChangeListener = window.addEventListener('webkitfullscreenchange', fullscreenChange);
webkitFullScreenChangeListener = window.addEventListener('fullscreenchange', fullscreenChange);
mozFullScreenChangeListener = window.addEventListener('mozfullscreenchange', fullscreenChange);
msFullScreenChangeListener = window.addEventListener('msfullscreenchange', fullscreenChange);
function fullscreenChange(event) {
var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement || document.webkitFullscreenElement;
if (!fullscreenElement) {
// exiting full screen
var targetElement = event.target;
// if this element contains a canvas, make it tiny so we don't mess up the size of its parent
// don't worry, the window.resize event that fires next will make it fill its parent just fine
var canvases = targetElement.getElementsByTagName('CANVAS');
for (var c = 0; c < canvases.length; c++) {
if (canvases[c] === htmlCanvas) {
canvases[c].width = 1;
canvases[c].height = 1;
canvases[c].style.width = '1px';
canvases[c].style.height = '1px';
break;
}
}
}
}
var guid = _Charts2.default.createGuid();
_ChartDictionary2.default.push({ id: guid, canvasElement: htmlCanvas, chart: this });
htmlCanvas.setAttribute('data-chart-id', guid);
// mousemove event
if (options.showValues) {
htmlCanvas.addEventListener('mouseout', handleMouseOut);
htmlCanvas.addEventListener('mousemove', function (event) {
var rect = htmlCanvas.getBoundingClientRect();
var pt = {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
handleMouseMove(pt);
});
htmlCanvas.addEventListener('mousedown', function (event) {
var rect = htmlCanvas.getBoundingClientRect();
var pt = {
x: event.clientX - rect.left,
y: event.clientY - rect.top
};
handleMouseClick(event, pt);
});
}
if (window.requestAnimationFrame) {
window.requestAnimationFrame(animateFrame);
} else if (window.webkitRequestAnimationFrame) {
window.webkitRequestAnimationFrame(animateFrame);
} else if (window.mozRequestAnimationFrame) {
window.mozRequestAnimationFrame(animateFrame);
} else if (window.oRequestAnimationFrame) {
window.oRequestAnimationFrame(animateFrame);
}
}
function handleMouseOut() {
for (var i = 0; i < data.length; i++) {
data[i].isHighlighted = false;
}
needsRender = true;
}
function handleMouseMove(pt) {
var hoveredDataSlice = hitTestPieSlices(pt, function (dataSlice) {
dataSlice.isHighlighted = true;
}, function (dataSlice) {
dataSlice.isHighlighted = false;
});
if (hoveredDataSlice) {
if (hoveredDataSlice.onClick) {
htmlCanvas.style.cursor = 'pointer';
} else {
htmlCanvas.style.cursor = 'default';
}
} else {
htmlCanvas.style.cursor = 'default';
}
needsRender = true;
}
function handleMouseClick(event, pt) {
var hoveredDataSlice = hitTestPieSlices(pt);
if (hoveredDataSlice) {
if (hoveredDataSlice.onClick) {
hoveredDataSlice.onClick(event);
}
}
}
function hitTestPieSlices(pt, onHit, onMiss) {
var ctx = htmlCanvas.getContext('2d');
// upscale this thang if the device pixel ratio is higher than 1
var backingStoreRatio = ctx.webkitBackingStorePixelRatio || ctx.mozBackingStorePixelRatio || ctx.msBackingStorePixelRatio || ctx.oBackingStorePixelRatio || ctx.backingStorePixelRatio || 1;
var canvasWidth = htmlCanvas.width / (pxRatio / backingStoreRatio);
var canvasHeight = htmlCanvas.height / (pxRatio / backingStoreRatio);
// determine the radius of the stinking pie chart
var pieRadius = plotVars.graphArea.height / 2;
if (plotVars.graphArea.width < plotVars.graphArea.height) {
pieRadius = plotVars.graphArea.width / 2;
}
// let's set a var for the center of the pie
var pieCenter = {
x: plotVars.graphArea.left + (canvasWidth - plotVars.graphArea.left - plotVars.graphArea.right) / 2,
y: plotVars.graphArea.top + (canvasHeight - plotVars.graphArea.top - plotVars.graphArea.bottom) / 2
};
// calculate the theta and radius based on the x, y
var theta = Math.atan((pt.y - pieCenter.y) / (pt.x - pieCenter.x));
if (pt.y >= pieCenter.y && pt.x >= pieCenter.x) {
// quadrant 1
theta += 0;
} else if (pt.y >= pieCenter.y && pt.x < pieCenter.x) {
// quadrant 2
theta += Math.PI;
} else if (pt.y < pieCenter.y && pt.x < pieCenter.x) {
// quadrant 3
theta += Math.PI;
} else if (pt.y < pieCenter.y && pt.x >= pieCenter.x) {
// quadrant 4
theta += 0;
}
var radius = Math.sqrt((pt.x - pieCenter.x) * (pt.x - pieCenter.x) + (pt.y - pieCenter.y) * (pt.y - pieCenter.y));
// calculate the total of all values
var totalValue = _lodash2.default.sum(data, function (datum) {
return datum.value;
});
// hit test all the pie slices
var highlightedDataSlice = null;
var movingRadian = -Math.PI / 2;
for (var i = 0; i < data.length; i++) {
var percent = data[i].value / totalValue;
var startRadian = movingRadian;
var endRadian = movingRadian + percent * Math.PI * 2;
// if the mouse is over this pie slice, mark it as highlighted
if (theta >= startRadian && theta < endRadian && radius <= pieRadius) {
if (onHit) {
onHit(data[i]);
}
highlightedDataSlice = data[i];
} else {
if (onMiss) {
onMiss(data[i]);
}
}
movingRadian += percent * Math.PI * 2;
}
// if you've already highlighted a pie slice, exit now
if (highlightedDataSlice) return highlightedDataSlice;
// hit test the legend
for (var i = 0; i < data.length; i++) {
if (data[i].boundingBox) {
if (pt.x >= data[i].boundingBox.x && pt.x < data[i].boundingBox.x + data[i].boundingBox.width && pt.y >= data[i].boundingBox.y && pt.y < data[i].boundingBox.y + data[i].boundingBox.height) {
if (onHit) {
onHit(data[i]);
}
highlightedDataSlice = data[i];
} else {
if (onMiss) {
onMiss(data[i]);
}
}
}
}
return highlightedDataSlice;
}
/***
* Fills the parent container with this canvas element
***/
function fillParent() {
if (htmlCanvas && htmlCanvas.parentNode) {
var style = window.getComputedStyle(htmlCanvas.parentNode);
var width = htmlCanvas.parentNode.offsetWidth - parseFloat(style.paddingLeft) - parseFloat(style.paddingRight);
var height = htmlCanvas.parentNode.offsetHeight - parseFloat(style.paddingTop) - parseFloat(style.paddingBottom);
// upscale this thang if the device pixel ratio is higher than 1
htmlCanvas.width = width * pxRatio;
htmlCanvas.height = height * pxRatio;
htmlCanvas.style.width = width + 'px';
htmlCanvas.style.height = height + 'px';
}
needsRender = true;
}
/***
* This function sets/resets the data for the graph
***/
this.setData = function (someData) {
data = someData.slice();
if (data && data.length) {
for (var i = 0; i < data.length; i++) {
var parts = _Numbers2.default.separateNumberUnits(data[i].value);
if (data[i].prefix === undefined) {
data[i].prefix = parts.prefix;
}
if (data[i].suffix === undefined) {
data[i].suffix = parts.suffix;
}
data[i].value = parts.value;
if (data[i].fillColor) {
data[i].fillColor = new _Color2.default.Color(data[i].fillColor);
} else {
data[i].fillColor = options.fillColor;
}
if (data[i].borderColor) {
data[i].borderColor = new _Color2.default.Color(data[i].borderColor);
} else {
data[i].borderColor = options.borderColor;
}
if (data[i].stripeColor) {
data[i].stripeColor = new _Color2.default.Color(data[i].stripeColor);
} else {
data[i].stripeColor = options.stripeColor;
}
}
//console.log(data);
}
needsRender = true;
};
/***
* The animateFrame method is called many times per second to calculate any
* movement needed in the graph. It then calls render() to update the display.
* Even if there is no animation in the graph this method ensures the view is updated frequently in case
* mouse events change the view
***/
function animateFrame() {
var thisFrame = new Date().getTime();
var elapsed = thisFrame - lastFrame; // elapsed time since last render
fps = 1000 / elapsed;
if (needsRender) {
self.render();
needsRender = false;
}
lastFrame = thisFrame;
if (!isDestroyed) {
if (window.requestAnimationFrame) {
window.requestAnimationFrame(animateFrame);
} else if (window.webkitRequestAnimationFrame) {
window.webkitRequestAnimationFrame(animateFrame);
} else if (window.mozRequestAnimationFrame) {
window.mozRequestAnimationFrame(animateFrame);
} else if (window.oRequestAnimationFrame) {
window.oRequestAnimationFrame(animateFrame);
}
}
}
var lastFrame = new Date().getTime(); // the timestamp of the last time the frame was last rendered
var fps = 0;
this.destroy = function () {
if (fullScreenChangeListener) {
window.removeEventListener('fullscreenchange', fullScreenChangeListener);
}
if (webkitFullScreenChangeListener) {
window.removeEventListener('webkitfullscreenchange', webkitFullScreenChangeListener);
}
if (mozFullScreenChangeListener) {
window.removeEventListener('mozfullscreenchange', mozFullScreenChangeListener);
}
if (msFullScreenChangeListener) {
window.removeEventListener('msfullscreenchange', msFullScreenChangeListener);
}
if (resizeListener) {
window.removeEventListener('resize', resizeListener);
}
if (htmlCanvas && htmlCanvas.parentNode) {
htmlCanvas.parentNode.removeChild(htmlCanvas);
}
isDestroyed = true;
};
// Initialize
_init.call(this);
};
exports.default = PieChart;