From 75ff4a845a83df96f811f42dde1499e72115e136 Mon Sep 17 00:00:00 2001 From: Giorgos Migdos Date: Sun, 30 Jun 2013 14:18:07 +0300 Subject: [PATCH] First attempt at supporting multiple data series. --- README.mkdn | 12 +- awesomechart.js | 1769 +++++++++--------------------------------- demo-animated.html | 311 -------- demo-multicolor.html | 292 ------- demo.html | 215 +---- 5 files changed, 399 insertions(+), 2200 deletions(-) delete mode 100644 demo-animated.html delete mode 100644 demo-multicolor.html diff --git a/README.mkdn b/README.mkdn index ad24534..5a5afd0 100644 --- a/README.mkdn +++ b/README.mkdn @@ -4,19 +4,11 @@ AwesomeChartJS is a small JavaScript chart rendering library based on the HTML 5 ##Chart types -* Vertical and horizontal bar charts -* Pareto bar charts -* Pie charts (whole or part) -* Exploded pie charts (whole or part) -* Ring/Doughnut charts (whole or part) +* Bar charts ##Animations -Now all charts except pareto bar charts can be animated when displayed. - -##Demo - -Go to demos page +All charts can be animated when displayed. ##Usage See demo.html diff --git a/awesomechart.js b/awesomechart.js index 7a8fa7a..36b4092 100644 --- a/awesomechart.js +++ b/awesomechart.js @@ -1,1391 +1,392 @@ /* -* Copyright 2011 Georgios Migdos -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ - -Array.prototype.numericSortReverse = function(data){ - this.sort(function(a, b){ - return data[b] - data[a]; - }); + * Copyright 2013 Georgios Migdos + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +function updateChart(awesomeChart) { + awesomeChart.ctx.clearRect(0, 0, awesomeChart.width, awesomeChart.height); + + awesomeChart.drawChart(awesomeChart.currentFrame); + + awesomeChart.drawTitleAndBorders(); + + if (awesomeChart.currentFrame < awesomeChart.animationFrames) { + awesomeChart.currentFrame++; + setTimeout(function() { + updateChart(awesomeChart); + }, 1000 / awesomeChart.animationFrames); + } } -Array.prototype.max = function() { - var max = this[0]; - var len = this.length; - for (var i = 1; i < len; i++){ - if (this[i] > max){ - max = this[i]; - } - } - return max; -} +function AwesomeChart(canvasElementId) { + var canvas = (typeof canvasElementId === 'string') ? document + .getElementById(canvasElementId) : canvasElementId; + this.ctx = canvas.getContext('2d'); + this.width = this.ctx.canvas.width; + this.height = this.ctx.canvas.height; + + this.numberOfDecimals = 0; + + this.proportionalSizes = true; + this.widthSizeFactor = 1; + this.heightSizeFactor = 1; + + this.chartType = 'bar'; + this.randomColors = false; + + this.animate = true; + this.animationFrames = 60; + this.currentFrame = 0; + + this.marginTop = 10; + this.marginBottom = 10; + this.marginLeft = 10; + this.marginRight = 10; + + this.labelMargin = 10; + this.dataValueMargin = 20; + this.titleMargin = 10; + this.yAxisLabelMargin = 5; + + this.data = new Array(); + this.labels = new Array(); + this.colors = new Array(); + this.title = null; + + this.backgroundFillStyle = 'rgba(255,255,255,0)'; + this.borderStrokeStyle = 'rgba(255,255,255,0)'; + this.borderWidth = 1.0; + + this.labelFillStyle = 'rgb(220, 36, 0)'; + this.labelFont = 'sans-serif'; + this.labelFontHeight = 12; + this.labelFontStyle = ''; + + this.dataValueFillStyle = '#333'; + this.dataValueFont = 'sans-serif'; + this.dataValueFontHeight = 15; + this.dataValueFontStyle = ''; + + this.titleFillStyle = '#333'; + this.titleFont = 'sans-serif'; + this.titleFontHeight = 16; + this.titleFontStyle = 'bold'; + + this.yAxisLabelFillStyle = '#333'; + this.yAxisLabelFont = 'sans-serif'; + this.yAxisLabelFontHeight = 10; + this.yAxisLabelFontStyle = ''; + + var lingrad = this.ctx.createLinearGradient(0, 0, 0, this.height); + lingrad.addColorStop(0.2, '#fdfdfd'); + lingrad.addColorStop(0.8, '#ededed'); + + this.chartBackgroundFillStyle = lingrad; + this.chartBorderStrokeStyle = '#999'; + this.chartBorderLineWidth = 1; + this.chartHorizontalLineStrokeStyle = '#999'; + this.chartHorizontalLineWidth = 1; + this.chartVerticalLineStrokeStyle = '#999'; + this.chartVerticalLineWidth = 1; + + this.chartMarkerSize = 5; + + this.chartPointRadius = 4; + this.chartPointFillStyle = 'rgb(150, 36, 0)'; + + this.chartLineStrokeStyle = 'rgba(150, 36, 0, 0.5)'; + this.chartLineWidth = 2; + + this.seriesHGap = 20; + this.seriesVGap = 20; +}; + +AwesomeChart.prototype = { + isArray : function(x) { + if (Object.prototype.toString.call(x) === Object.prototype.toString + .call([])) { + return true; + } + return false; + }, + + arrayNumericSortReverse : function(arr, data) { + arr.sort(function(a, b) { + return data[b] - data[a]; + }); + }, + + dataMax : function(arr) { + var max = null; + var tmp = null; + for ( var a in arr) { + tmp = Math.max.apply(null, arr[a]); + if ((max == null) || (max < tmp)) { + max = tmp; + } + } + return max; + }, + + dataMin : function(arr) { + var min = null; + var tmp = null; + for ( var a in arr) { + tmp = Math.min.apply(null, arr[a]); + if ((min == null) || (min < tmp)) { + min = tmp; + } + } + return min; + }, + + maxSeriesLength : function(arr) { + var len = 0; + for ( var a in arr) { + tmp = arr[a].length; + if (len <= tmp) { + len = tmp; + } + } + return len; + }, + + generateRandomColor : function() { + var rgb = new Array(); + for ( var i = 0; i < 3; i++) { + rgb.push(Math.ceil(Math.random() * 150 + 50)); + } + return 'rgb(' + rgb.join(",") + ')'; + }, + + draw : function() { + var context = this.ctx; + context.lineCap = 'round'; + var minFactor = Math.min(this.widthSizeFactor, this.heightSizeFactor); + + if (this.proportionalSizes) { + this.labelMargin = this.labelMargin * this.heightSizeFactor; + this.dataValueMargin = this.dataValueMargin * this.heightSizeFactor; + this.titleMargin = this.titleMargin * this.heightSizeFactor; + this.yAxisLabelMargin = this.yAxisLabelMargin + * this.heightSizeFactor; + + this.labelFontHeight = this.labelFontHeight * minFactor; + this.dataValueFontHeight = this.dataValueFontHeight * minFactor; + this.titleFontHeight = this.titleFontHeight * minFactor; + this.yAxisLabelFontHeight = this.yAxisLabelFontHeight * minFactor; + } + + if (this.randomColors) { + for ( var i in this.data) { + this.colors[i] = this.generateRandomColor(); + } + } + + if (!this.animate) { + this.currentFrame = this.animationFrames; + } else { + this.currentFrame = 0; + } + + updateChart(this); + + }, + + drawTitleAndBorders : function() { + var context = this.ctx; + + if (this.title != null) { + // Draw the title: + + context.font = this.titleFontStyle + ' ' + this.titleFontHeight + + 'px ' + this.titleFont; + context.fillStyle = this.titleFillStyle; + context.textAlign = 'center'; + context.textBaseline = 'bottom'; + context.fillText(this.title, this.width / 2, this.marginTop + + this.titleFontHeight, this.width - 10); + } + + // Draw the outer border: + + context.lineWidth = this.borderWidth; + context.strokeStyle = this.borderStrokeStyle; + context.strokeRect(0, 0, this.width, this.height); + + context.globalCompositeOperation = 'destination-over'; + + // Fill the background: + + context.fillStyle = this.backgroundFillStyle; + context.fillRect(0, 0, this.width, this.height); + + context.globalCompositeOperation = 'source-over'; + }, + + drawChart : function(frameNumber) { + } +}; + +function AwesomeBarChart(canvasElementId) { + + AwesomeChart.call(this, canvasElementId); + + this.barFillStyle = 'rgb(220, 36, 0)'; + this.barStrokeStyle = '#fff'; + this.barBorderWidth = 2.0; + this.barShadowColor = 'rgba(0, 0, 0, 0.5)'; + this.barShadowBlur = 5; + this.barShadowOffsetX = 3.0; + this.barShadowOffsetY = 0.0; +}; + +AwesomeBarChart.prototype = Object.create(AwesomeChart.prototype); + +function AwesomeHorizontalBarChart(canvasElementId) { + + AwesomeBarChart.call(this, canvasElementId); + this.barHGap = 5; + + var parentDraw = this.draw; + + this.draw = function() { + this.barHGap = this.barHGap * this.widthSizeFactor; + this.barVGap = this.barHGap * this.heightSizeFactor; + parentDraw.call(this); + }; + + this.drawChart = function(frameNumber) { + var context = this.ctx; + // Calculate bar size: + + var n = this.maxSeriesLength(this.data); + var numOfSeries = Object.keys(this.data).length; + var maxData = this.dataMax(this.data); + var minData = this.dataMin(this.data); + + var barWidth = (this.width - this.marginLeft - this.marginRight - (((numOfSeries - 1) + * n * this.barHGap) + (n * this.seriesHGap))) + / (n * numOfSeries); + + var barMaxTopY = this.marginTop + this.labelMargin + + this.labelFontHeight + this.dataValueMargin + + this.dataValueFontHeight; + + var barMinTopY = this.height - this.marginBottom; + + if (this.title != null) { + barMaxTopY += this.titleFontHeight + this.titleMargin; + } + + var barBottomY = this.height - this.marginBottom; + + if (minData < 0) { -Array.prototype.min = function() { - var min = this[0]; - var len = this.length; - for (var i = 1; i < len; i++){ - if (this[i] < min){ - min = this[i]; - } - } - return min; -} + barMinTopY = this.height - this.marginBottom - this.labelMargin + - this.labelFontHeight - this.dataValueMargin + - this.dataValueFontHeight; + + barBottomY = barMinTopY + + ((this.height - this.marginBottom - barMaxTopY + - this.labelMargin - this.labelFontHeight + - this.dataValueMargin - this.dataValueFontHeight) * minData) + / (Math.abs(minData) + maxData); + + } + + var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math + .abs(barBottomY - barMinTopY)); + var maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData)); + + var x = this.marginLeft; + var y = barBottomY; + var barHeight = 0; + + for ( var i = 0; i < n; i++) { + + for ( var series in this.data) { + di = this.data[series][i]; + barHeight = (di * frameNumber / this.animationFrames) + * maxBarHeight / maxBarAbsData; -function AwesomeChart(canvasElementId){ - var canvas = (typeof canvasElementId === 'string') ? document.getElementById(canvasElementId) : canvasElementId; - this.ctx = canvas.getContext('2d'); - this.width = this.ctx.canvas.width; - this.height = this.ctx.canvas.height; - - this.numberOfDecimals = 0; - - this.proportionalSizes = true; - this.widthSizeFactor = this.width/400; - this.heightSizeFactor = this.height/400; - - this.chartType = 'bar'; - this.randomColors = false; - - this.animate = false; - this.animationFrames = 60; - - this.marginTop = 10; - this.marginBottom = 10; - this.marginLeft = 10; - this.marginRight = 10; - - this.labelMargin = 10; - this.dataValueMargin = 20; - this.titleMargin = 10; - this.yAxisLabelMargin = 5; - - this.data = new Array(); - this.labels = new Array(); - this.colors = new Array(); - this.title = null; - - this.backgroundFillStyle = 'rgba(255,255,255,0)'; - this.borderStrokeStyle = 'rgba(255,255,255,0)'; - this.borderWidth = 1.0; - - this.labelFillStyle = 'rgb(220, 36, 0)'; - this.labelFont = 'sans-serif'; - this.labelFontHeight = 12; - this.labelFontStyle = ''; - - this.dataValueFillStyle = '#333'; - this.dataValueFont = 'sans-serif'; - this.dataValueFontHeight = 15; - this.dataValueFontStyle = ''; - - this.titleFillStyle = '#333'; - this.titleFont = 'sans-serif'; - this.titleFontHeight = 16; - this.titleFontStyle = 'bold'; - - this.yAxisLabelFillStyle = '#333'; - this.yAxisLabelFont = 'sans-serif'; - this.yAxisLabelFontHeight = 10; - this.yAxisLabelFontStyle = ''; - - var lingrad = this.ctx.createLinearGradient(0,0,0,this.height); - lingrad.addColorStop(0.2, '#fdfdfd'); - lingrad.addColorStop(0.8, '#ededed'); - - this.chartBackgroundFillStyle = lingrad; - this.chartBorderStrokeStyle = '#999'; - this.chartBorderLineWidth = 1; - this.chartHorizontalLineStrokeStyle = '#999'; - this.chartHorizontalLineWidth = 1; - this.chartVerticalLineStrokeStyle = '#999'; - this.chartVerticalLineWidth = 1; - - this.chartMarkerSize = 5; - - this.chartPointRadius = 4; - this.chartPointFillStyle = 'rgb(150, 36, 0)'; - - this.chartLineStrokeStyle = 'rgba(150, 36, 0, 0.5)'; - this.chartLineWidth = 2; - - this.barFillStyle = 'rgb(220, 36, 0)'; - this.barStrokeStyle = '#fff'; - this.barBorderWidth = 2.0; - this.barShadowColor = 'rgba(0, 0, 0, 0.5)'; - this.barShadowBlur = 5; - this.barShadowOffsetX = 3.0; - this.barShadowOffsetY = 0.0; - - this.barHGap = 20; - this.barVGap = 20; - - this.explosionOffset = 20; - - this.pieFillStyle = 'rgb(220, 36, 0)'; - this.pieStrokeStyle = '#fff'; - this.pieBorderWidth = 2.0; - this.pieShadowColor = 'rgba(0, 0, 0, 0.5)'; - this.pieShadowBlur = 5; - this.pieShadowOffsetX = 3.0; - this.pieShadowOffsetY = 0.0; - - this.pieStart = 0; - this.pieTotal = null; - - this.generateRandomColor = function(){ - var rgb = new Array(); - for(var i=0; i<3; i++){ - rgb.push(Math.ceil(Math.random()*150 + 50)); - } - return 'rgb('+rgb.join(",")+')'; - } - - /*Set the chart's data in the format: - * - * { - * "label-1": data-value-1, - * "label-2": data-value-2, - * "label-3": data-value-3, - * .... - * "label-N": data-value-N, - * } - * - */ - this.setChartDataFromJSON = function(jsonObj){ - for(var p in jsonObj){ - this.labels.push(p); - this.data.push(jsonObj[p]); - } - } - - - this.draw = function(){ - var context = this.ctx; - context.lineCap = 'round'; - var minFactor = Math.min(this.widthSizeFactor, this.heightSizeFactor); - - if(this.proportionalSizes){ - this.labelMargin = this.labelMargin * this.heightSizeFactor; - this.dataValueMargin = this.dataValueMargin * this.heightSizeFactor; - this.titleMargin = this.titleMargin * this.heightSizeFactor; - this.yAxisLabelMargin = this.yAxisLabelMargin * this.heightSizeFactor; - - this.labelFontHeight = this.labelFontHeight * minFactor; - this.dataValueFontHeight = this.dataValueFontHeight * minFactor; - this.titleFontHeight = this.titleFontHeight * minFactor; - this.yAxisLabelFontHeight = this.yAxisLabelFontHeight * minFactor; - - this.barHGap = this.barHGap * this.widthSizeFactor; - this.barVGap = this.barHGap * this.heightSizeFactor; - this.explosionOffset = this.explosionOffset * minFactor; - } - - if(this.randomColors){ - for(var i=0; i=0){ - context.textBaseline = 'bottom'; - context.fillText(this.labels[i], x + barWidth/2, barBottomY - barHeight - this.labelMargin, barWidth); - }else{ - context.textBaseline = 'top'; - context.fillText(this.labels[i], x + barWidth/2, barBottomY - barHeight + this.labelMargin, barWidth); - } - } - - //Draw the data value: - - context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont; - context.fillStyle = this.dataValueFillStyle; - context.textAlign = 'center'; - if(di>=0){ - context.textBaseline = 'bottom'; - context.fillText(di, x + barWidth/2, barBottomY - barHeight - this.labelMargin - this.dataValueMargin, barWidth); - }else{ - context.textBaseline = 'top'; - context.fillText(di, x + barWidth/2, barBottomY - barHeight + this.labelMargin + this.dataValueMargin, barWidth); - } - - - //Update x: - - x = x + barWidth + this.barHGap; - } - } - - - - this.animateBarChart = function() { - var aw = this, - numFrames = this.animationFrames, - currentFrame = 0, - - maxData = this.data.max(), - minData = this.data.min(), - - barMaxTopY = this.marginTop + this.labelMargin + this.labelFontHeight + this.dataValueMargin + this.dataValueFontHeight, - barMinTopY = barBottomY = this.height - this.marginBottom; - - if(this.title!=null){ - barMaxTopY += this.titleFontHeight + this.titleMargin; - } - - if(minData<0){ - barMinTopY = this.height - this.marginBottom - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight; - - barBottomY = barMinTopY + ((this.height - this.marginBottom - barMaxTopY - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight) * minData) / (Math.abs(minData)+maxData); - } - - var chartAreaHeight = barMinTopY - barMaxTopY, - changeOfMarginBottom = 0, - changeOfMarginTop = 0; - - var belowZeroMaxBarHeight = 0; - if(minData<0){ - var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math.abs(barBottomY - barMinTopY)), - maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData)); - belowZeroMaxBarHeight = Math.abs(minData * maxBarHeight / maxBarAbsData + this.labelMargin + this.labelFontHeight); - } - - this.marginBottom += belowZeroMaxBarHeight; - if(this.title!=null){ - this.titleMargin += chartAreaHeight - belowZeroMaxBarHeight; - }else{ - this.marginTop += chartAreaHeight - belowZeroMaxBarHeight; - } - changeOfMarginBottom = belowZeroMaxBarHeight / numFrames; - changeOfMarginTop = (chartAreaHeight - belowZeroMaxBarHeight) / numFrames; - - var updateBarChart = function() { - if(currentFrame++ < numFrames) { - - aw.marginBottom -= changeOfMarginBottom; - - if(aw.title!=null){ - aw.titleMargin -= changeOfMarginTop; - }else{ - aw.marginTop -= changeOfMarginTop; - } - - aw.ctx.clearRect(0, 0, aw.width, aw.height); - aw.drawBarChart(); - aw.drawTitleAndBorders(); - - // Standard - if (typeof(window.requestAnimationFrame) == 'function') { - window.requestAnimationFrame(updateBarChart); - - // IE 10+ - } else if (typeof(window.msRequestAnimationFrame) == 'function') { - window.msRequestAnimationFrame(updateBarChart); - - // Chrome - } else if (typeof(window.webkitRequestAnimationFrame) == 'function') { - window.webkitRequestAnimationFrame(updateBarChart); - - // Firefox - } else if (window.mozRequestAnimationFrame) { // Seems rather slow in FF6 - so disabled - window.mozRequestAnimationFrame(updateBarChart); - - // Default fallback to setTimeout - } else { - setTimeout(updateBarChart, 16.6666666); - } - } - } - - updateBarChart(); - - } - - - - this.drawVerticalBarChart = function(){ - var context = this.ctx; - - context.save(); - context.translate(this.width/2, this.height/2); - context.rotate(Math.PI/2); - context.translate(-this.width/2, -this.height/2); - - //Calculate bar size: - - var n = this.data.length; - var maxData = this.data.max(); - var minData = this.data.min(); - - var marginLeft = this.marginLeft; - if(this.title!=null){ - marginLeft += this.titleFontHeight + this.titleMargin; - } - - var barWidth = (this.width - marginLeft - this.marginRight - (n-1) * this.barHGap) / n; - - context.font = this.labelFontStyle + ' ' + this.labelFontHeight + 'px '+ this.labelFont; - var maxLabelWidth = 0; - var labelWidth = 0; - for(var i=0; imaxLabelWidth){ - maxLabelWidth = labelWidth; - } - } - - context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont; - var maxDataValueWidth = 0; - var dataValueWidth = 0; - for(var i=0; imaxDataValueWidth){ - maxDataValueWidth = dataValueWidth; - } - } - - var barMaxTopY = this.marginTop + Math.max( (this.labelMargin + maxLabelWidth), (this.dataValueMargin + maxDataValueWidth) ); - - var barMinTopY = this.height - this.marginBottom; - - var barBottomY = this.height - this.marginBottom; - - if(minData<0){ - - barMinTopY = this.height - this.marginBottom - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight; - - barBottomY = barMinTopY + ((this.height - this.marginBottom - barMaxTopY - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight) * minData) / (Math.abs(minData)+maxData); - - } - - - var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math.abs(barBottomY - barMinTopY)); - var maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData)); - - var x = marginLeft; - var y = barBottomY; - var barHeight = 0; - - var di = 0; - - for(var i=0; i=0){ - context.textAlign = 'left'; - context.fillText(this.labels[i], this.labelMargin, 0); - }else{ - context.textAlign = 'right'; - context.fillText(this.labels[i], -this.labelMargin, 0); - } - } - - //Draw the data value: - - context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont; - context.fillStyle = this.dataValueFillStyle; - context.textBaseline = 'bottom'; - if(di>=0){ - context.textAlign = 'left'; - context.fillText(di, this.labelMargin, 0); - }else{ - context.textAlign = 'right'; - context.fillText(di, -this.labelMargin, 0); - } - - context.restore(); - - //Update x: - - x = x + barWidth + this.barHGap; - } - - context.restore(); - - } - - - - this.animateVerticalBarChart = function() { - var aw = this, - numFrames = this.animationFrames, - currentFrame = 0, - - maxData = this.data.max(), - minData = this.data.min(), - dataLen = this.data.length, - - context = this.ctx, - - marginLeft = this.marginLeft - marginTop = this.marginTop - marginTopCurrent = 0; - - - if(this.title!=null){ - marginLeft += this.titleFontHeight + this.titleMargin; - } - - var barWidth = (this.width - marginLeft - this.marginRight - (dataLen-1) * this.barHGap) / dataLen; - - context.font = this.labelFontStyle + ' ' + this.labelFontHeight + 'px '+ this.labelFont; - var maxLabelWidth = 0; - var labelWidth = 0; - for(var i=0; imaxLabelWidth){ - maxLabelWidth = labelWidth; - } - } - - context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont; - var maxDataValueWidth = 0; - var dataValueWidth = 0; - for(var i=0; imaxDataValueWidth){ - maxDataValueWidth = dataValueWidth; - } - } - - var barMaxTopY = this.marginTop + Math.max( (this.labelMargin + maxLabelWidth), (this.dataValueMargin + maxDataValueWidth) ); - - var barMinTopY = this.height - this.marginBottom; - - var barBottomY = this.height - this.marginBottom; - - if(minData<0){ - - barMinTopY = this.height - this.marginBottom - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight; - - barBottomY = barMinTopY + ((this.height - this.marginBottom - barMaxTopY - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight) * minData) / (Math.abs(minData)+maxData); - - } - - - var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math.abs(barBottomY - barMinTopY)); - var maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData)); - - - var belowZeroMaxBarHeight = 0; - if(minData<0){ - belowZeroMaxBarHeight = Math.abs(minData * maxBarHeight / maxBarAbsData); - } - - var chartAreaHeight = maxData * maxBarHeight / maxBarAbsData + belowZeroMaxBarHeight, - changeOfMarginBottom = 0, - changeOfMarginTop = 0; - - this.marginBottom += belowZeroMaxBarHeight; - this.marginTop += chartAreaHeight - belowZeroMaxBarHeight; - changeOfMarginBottom = belowZeroMaxBarHeight / numFrames; - changeOfMarginTop = (chartAreaHeight - belowZeroMaxBarHeight) / numFrames; - - var updateVerticalBarChart = function() { - if(currentFrame++ < numFrames) { - - aw.marginBottom -= changeOfMarginBottom; - aw.marginTop -= changeOfMarginTop; - - aw.ctx.clearRect(0, 0, aw.width, aw.height); - aw.drawVerticalBarChart(); - - marginTopCurrent = aw.marginTop; - aw.marginTop = marginTop; - aw.drawTitleAndBorders(); - aw.marginTop = marginTopCurrent; - - // Standard - if (typeof(window.requestAnimationFrame) == 'function') { - window.requestAnimationFrame(updateVerticalBarChart); - - // IE 10+ - } else if (typeof(window.msRequestAnimationFrame) == 'function') { - window.msRequestAnimationFrame(updateVerticalBarChart); - - // Chrome - } else if (typeof(window.webkitRequestAnimationFrame) == 'function') { - window.webkitRequestAnimationFrame(updateVerticalBarChart); - - // Firefox - } else if (window.mozRequestAnimationFrame) { // Seems rather slow in FF6 - so disabled - window.mozRequestAnimationFrame(updateVerticalBarChart); - - // Default fallback to setTimeout - } else { - setTimeout(updateVerticalBarChart, 16.6666666); - } - } - } - - updateVerticalBarChart(); - - } - - - - this.drawPieChart = function(ring){ - var context = this.ctx; - context.lineWidth = this.pieBorderWidth; - - var dataSum = 0, - dataSumForStartAngle = 0, - dataLen = this.data.length; - - for (var i=0; imaxLabelWidth){ - maxLabelWidth = labelWidth; - } - } - - radius = radius - maxLabelWidth - this.labelMargin; - - var startAngle = this.pieStart* doublePI / dataSumForStartAngle; - var currentAngle = startAngle; - var endAngle = 0; - var incAngleBy = 0; - - for(var i=0; iMath.PI/2) && (mAngle<=3*(Math.PI/2)) ){ - var translateXBy = radius + this.labelMargin + context.measureText(this.labels[i]).width / 2; - context.translate(translateXBy, 0); - context.rotate(Math.PI); - context.translate(-translateXBy, 0); - } - context.textBaseline = 'middle'; - context.fillText(this.labels[i], radius+this.labelMargin, 0); - } - - context.restore(); - currentAngle = endAngle; - } - } - - - - this.drawExplodedPieChart = function(){ - var context = this.ctx; - context.lineWidth = this.pieBorderWidth; - - var dataSum = 0, - dataSumForStartAngle = 0, - dataLen = this.data.length; - - for (var i=0; imaxLabelWidth){ - maxLabelWidth = labelWidth; - } - } - - radius = radius - maxLabelWidth - this.labelMargin; - - var currentAngle = this.pieStart* doublePI / dataSumForStartAngle; - var endAngle = 0; - var incAngleBy = 0; - var halfAngle = 0; - var mAngle = 0; - for(var i=0; iMath.PI/2) && (mAngle<=3*(Math.PI/2)) ){ - var translateXBy = radius + this.labelMargin + context.measureText(this.labels[i]).width / 2; - context.translate(translateXBy, 0); - context.rotate(Math.PI); - context.translate(-translateXBy, 0); - } - context.textBaseline = 'middle'; - context.fillText(this.labels[i], radius+this.labelMargin, 0); - } - - - // Restore the context: - - context.restore(); - currentAngle = endAngle; - - } - - } - - - - this.animatePieChart = function(pieType){ - var dataSum = 0, - pieTotalReal = this.pieTotal, - aw = this, - numFrames = this.animationFrames, - currentFrame = 0, - pieAreaWidth = this.width - this.marginLeft - this.marginRight, - pieAreaHeight = this.height - this.marginTop - this.marginBottom, - marginTop = this.marginTop, - marginLeft = this.marginLeft; - - if(this.title){ - pieAreaHeight = pieAreaHeight - this.titleFontHeight - this.titleMargin; - marginTop += this.titleFontHeight + this.titleMargin; - }; - - for(var i=0; imaxYAxisLabelWidth){ - maxYAxisLabelWidth = yAxisLabelWidth; - } - } - - var perCentMaxWidth = context.measureText("100%").width; - - // Calculate the chart size and position: - - var chartWidth = this.width - this.marginLeft - this.marginRight - 2*this.chartMarkerSize - maxYAxisLabelWidth - perCentMaxWidth - 2*this.yAxisLabelMargin; - var chartHeight = this.height - this.marginTop - this.marginBottom; - - var chartTopLeftX = this.marginLeft + this.chartMarkerSize + maxYAxisLabelWidth + this.yAxisLabelMargin; - var chartTopLeftY = this.marginTop; - - - if(this.title){ - chartHeight -= this.titleFontHeight + this.titleMargin; - chartTopLeftY += this.titleFontHeight + this.titleMargin; - } - - - // Draw the chart's background: - - context.save(); - - context.translate(chartTopLeftX, chartTopLeftY); - - context.fillStyle = this.chartBackgroundFillStyle; - context.fillRect(0,0,chartWidth,chartHeight); - - - // Draw the markers, horizontal lines, and axis' labels: - - var yStep = chartHeight / 10; - var lineY = 0; - - context.lineWidth = this.chartHorizontalLineWidth; - context.font = this.yAxisLabelFontStyle + ' ' + this.yAxisLabelFontHeight + 'px '+ this.yAxisLabelFont; - - for(var i=0; i<=10; i++){ - lineY = i*yStep; - - if( i>0 && i<10){ - - context.strokeStyle = this.chartHorizontalLineStrokeStyle; - context.beginPath(); - context.moveTo(0,lineY); - context.lineTo(chartWidth,lineY); - context.stroke(); - - } - - context.strokeStyle = this.chartBorderStrokeStyle; - context.beginPath(); - context.moveTo(-this.chartMarkerSize,lineY); - context.lineTo(0,lineY); - context.stroke(); - - context.beginPath(); - context.moveTo(chartWidth,lineY); - context.lineTo(chartWidth+this.chartMarkerSize,lineY); - context.stroke(); - - context.fillStyle = this.yAxisLabelFillStyle; - context.textAlign = 'right'; - context.textBaseline = 'middle'; - context.fillText(yAxisValues[10-i], -this.chartMarkerSize-this.yAxisLabelMargin, lineY); - - context.textAlign = 'left'; - context.fillText( ((10-i)*10)+'%', chartWidth+this.chartMarkerSize+this.yAxisLabelMargin, lineY); - } - - // Draw the bars: - - context.save(); - - context.translate(0, chartHeight); - - var barWidth = (chartWidth-2*this.barHGap) / n; - var barHeight = 0; - - var halfBarWidth = barWidth/2; - - var y = 0; - var x = this.barHGap; - var x1 = x; - var y1 = 0; - var x2 = 0; - var y2 = 0; - - for(var i=0; i=0){ - context.textBaseline = 'bottom'; - context.fillText(this.labels[indices[i]], x + halfBarWidth, - barHeight - this.labelMargin, barWidth); - }else{ - context.textBaseline = 'top'; - context.fillText(this.labels[indices[i]], x + halfBarWidth, - barHeight + this.labelMargin, barWidth); - } - } - - // Draw the data value: - - context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont; - context.fillStyle = this.dataValueFillStyle; - context.textAlign = 'center'; - if(this.data[indices[i]]>=0){ - context.textBaseline = 'bottom'; - context.fillText(this.data[indices[i]], x + halfBarWidth, - barHeight - this.labelMargin - this.dataValueMargin, barWidth); - }else{ - context.textBaseline = 'top'; - context.fillText(this.data[indices[i]], x + halfBarWidth, - barHeight + this.labelMargin + this.dataValueMargin, barWidth); - } - - - // Update x: - - x = x + barWidth; - - } - - // Draw the points: - - x = this.barHGap; - x1 = x; - y1 = 0; - x2 = 0; - y2 = 0; - - context.fillStyle = this.chartPointFillStyle; - context.beginPath(); - context.arc(x1, y1, this.chartPointRadius, 0, 2*Math.PI, false); - context.fill(); - - for(var i=0; i= 0) { + context.textBaseline = 'bottom'; + context.fillText(series, x + barWidth / 2, barBottomY + - barHeight - this.labelMargin, barWidth); + } else { + context.textBaseline = 'top'; + context.fillText(series, x + barWidth / 2, barBottomY + - barHeight + this.labelMargin, barWidth); + } + + // Draw the data value: + + context.font = this.dataValueFontStyle + ' ' + + this.dataValueFontHeight + 'px ' + this.dataValueFont; + context.fillStyle = this.dataValueFillStyle; + context.textAlign = 'center'; + if (di >= 0) { + context.textBaseline = 'bottom'; + context.fillText(di, x + barWidth / 2, barBottomY + - barHeight - this.labelMargin + - this.dataValueMargin, barWidth); + } else { + context.textBaseline = 'top'; + context.fillText(di, x + barWidth / 2, barBottomY + - barHeight + this.labelMargin + + this.dataValueMargin, barWidth); + } + + // Update x: + + x += barWidth + this.barHGap; + } + x += this.seriesHGap; + + } + }; } +AwesomeHorizontalBarChart.prototype = Object.create(AwesomeBarChart.prototype); diff --git a/demo-animated.html b/demo-animated.html deleted file mode 100644 index efea5e4..0000000 --- a/demo-animated.html +++ /dev/null @@ -1,311 +0,0 @@ - - - - AwesomeChartJS demo - - - - -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- - - - - - - - diff --git a/demo-multicolor.html b/demo-multicolor.html deleted file mode 100644 index dadc064..0000000 --- a/demo-multicolor.html +++ /dev/null @@ -1,292 +0,0 @@ - - - - AwesomeChartJS demo - - - - -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- - - - - - - - diff --git a/demo.html b/demo.html index 90abec4..9719ee1 100644 --- a/demo.html +++ b/demo.html @@ -46,221 +46,30 @@ -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- +
- + Your web-browser does not support the HTML 5 canvas element.
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- -
-
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
- -
-
- - Your web-browser does not support the HTML 5 canvas element. - - -
- -
- - - Your web-browser does not support the HTML 5 canvas element. - - -
-
- - +