27 |
28 | Source code is available under the terms of the [Apache license v2.0](http://www.apache.org/licenses/LICENSE-2.0).
29 |
30 |
31 | ##Contributors
32 |
33 | * [pkozlowski-opensource](https://github.com/pkozlowski-opensource)
34 | * [barszczmm](https://github.com/barszczmm)
35 |
--------------------------------------------------------------------------------
/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AwesomeChartJS demo
5 |
46 |
47 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
63 |
64 |
65 |
66 |
67 |
68 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
81 |
82 |
83 |
84 |
85 |
86 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
99 |
100 |
101 |
102 |
103 |
104 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
117 |
118 |
119 |
120 |
121 |
122 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
135 |
136 |
137 |
138 |
139 |
140 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
150 |
153 |
154 |
155 |
156 |
157 |
158 |
161 |
162 |
163 |
164 |
165 |
166 |
167 |
265 |
266 |
267 |
268 |
269 |
--------------------------------------------------------------------------------
/demo-multicolor.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AwesomeChartJS demo
5 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
98 |
99 |
100 |
101 |
102 |
103 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
116 |
117 |
118 |
119 |
120 |
121 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
139 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
152 |
153 |
154 |
155 |
156 |
157 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
289 |
290 |
291 |
292 |
293 |
--------------------------------------------------------------------------------
/demo-animated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | AwesomeChartJS demo
5 |
45 |
46 |
47 |
48 |
49 |
50 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
62 |
63 |
64 |
65 |
66 |
67 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
80 |
81 |
82 |
83 |
84 |
85 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
98 |
99 |
100 |
101 |
102 |
103 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
116 |
117 |
118 |
119 |
120 |
121 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
139 |
142 |
143 |
144 |
145 |
146 |
147 |
148 |
149 |
152 |
153 |
154 |
155 |
156 |
157 |
160 |
161 |
162 |
163 |
164 |
165 |
166 |
308 |
309 |
310 |
311 |
312 |
--------------------------------------------------------------------------------
/awesomechart.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright 2011 Georgios Migdos
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License");
5 | * you may not use this file except in compliance with the License.
6 | * You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software
11 | * distributed under the License is distributed on an "AS IS" BASIS,
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 | * See the License for the specific language governing permissions and
14 | * limitations under the License.
15 | */
16 |
17 | Array.prototype.numericSortReverse = function(data){
18 | this.sort(function(a, b){
19 | return data[b] - data[a];
20 | });
21 | }
22 |
23 | Array.prototype.max = function() {
24 | var max = this[0];
25 | var len = this.length;
26 | for (var i = 1; i < len; i++){
27 | if (this[i] > max){
28 | max = this[i];
29 | }
30 | }
31 | return max;
32 | }
33 |
34 | Array.prototype.min = function() {
35 | var min = this[0];
36 | var len = this.length;
37 | for (var i = 1; i < len; i++){
38 | if (this[i] < min){
39 | min = this[i];
40 | }
41 | }
42 | return min;
43 | }
44 |
45 | function AwesomeChart(canvasElementId){
46 | var canvas = (typeof canvasElementId === 'string') ? document.getElementById(canvasElementId) : canvasElementId;
47 | this.ctx = canvas.getContext('2d');
48 | this.width = this.ctx.canvas.width;
49 | this.height = this.ctx.canvas.height;
50 |
51 | this.numberOfDecimals = 0;
52 |
53 | this.proportionalSizes = true;
54 | this.widthSizeFactor = this.width/400;
55 | this.heightSizeFactor = this.height/400;
56 |
57 | this.chartType = 'bar';
58 | this.randomColors = false;
59 |
60 | this.animate = false;
61 | this.animationFrames = 60;
62 |
63 | this.marginTop = 10;
64 | this.marginBottom = 10;
65 | this.marginLeft = 10;
66 | this.marginRight = 10;
67 |
68 | this.labelMargin = 10;
69 | this.dataValueMargin = 20;
70 | this.titleMargin = 10;
71 | this.yAxisLabelMargin = 5;
72 |
73 | this.data = new Array();
74 | this.labels = new Array();
75 | this.colors = new Array();
76 | this.title = null;
77 |
78 | this.backgroundFillStyle = 'rgba(255,255,255,0)';
79 | this.borderStrokeStyle = 'rgba(255,255,255,0)';
80 | this.borderWidth = 1.0;
81 |
82 | this.labelFillStyle = 'rgb(220, 36, 0)';
83 | this.labelFont = 'sans-serif';
84 | this.labelFontHeight = 12;
85 | this.labelFontStyle = '';
86 |
87 | this.dataValueFillStyle = '#333';
88 | this.dataValueFont = 'sans-serif';
89 | this.dataValueFontHeight = 15;
90 | this.dataValueFontStyle = '';
91 |
92 | this.titleFillStyle = '#333';
93 | this.titleFont = 'sans-serif';
94 | this.titleFontHeight = 16;
95 | this.titleFontStyle = 'bold';
96 |
97 | this.yAxisLabelFillStyle = '#333';
98 | this.yAxisLabelFont = 'sans-serif';
99 | this.yAxisLabelFontHeight = 10;
100 | this.yAxisLabelFontStyle = '';
101 |
102 | var lingrad = this.ctx.createLinearGradient(0,0,0,this.height);
103 | lingrad.addColorStop(0.2, '#fdfdfd');
104 | lingrad.addColorStop(0.8, '#ededed');
105 |
106 | this.chartBackgroundFillStyle = lingrad;
107 | this.chartBorderStrokeStyle = '#999';
108 | this.chartBorderLineWidth = 1;
109 | this.chartHorizontalLineStrokeStyle = '#999';
110 | this.chartHorizontalLineWidth = 1;
111 | this.chartVerticalLineStrokeStyle = '#999';
112 | this.chartVerticalLineWidth = 1;
113 |
114 | this.chartMarkerSize = 5;
115 |
116 | this.chartPointRadius = 4;
117 | this.chartPointFillStyle = 'rgb(150, 36, 0)';
118 |
119 | this.chartLineStrokeStyle = 'rgba(150, 36, 0, 0.5)';
120 | this.chartLineWidth = 2;
121 |
122 | this.barFillStyle = 'rgb(220, 36, 0)';
123 | this.barStrokeStyle = '#fff';
124 | this.barBorderWidth = 2.0;
125 | this.barShadowColor = 'rgba(0, 0, 0, 0.5)';
126 | this.barShadowBlur = 5;
127 | this.barShadowOffsetX = 3.0;
128 | this.barShadowOffsetY = 0.0;
129 |
130 | this.barHGap = 20;
131 | this.barVGap = 20;
132 |
133 | this.explosionOffset = 20;
134 |
135 | this.pieFillStyle = 'rgb(220, 36, 0)';
136 | this.pieStrokeStyle = '#fff';
137 | this.pieBorderWidth = 2.0;
138 | this.pieShadowColor = 'rgba(0, 0, 0, 0.5)';
139 | this.pieShadowBlur = 5;
140 | this.pieShadowOffsetX = 3.0;
141 | this.pieShadowOffsetY = 0.0;
142 |
143 | this.pieStart = 0;
144 | this.pieTotal = null;
145 |
146 | this.generateRandomColor = function(){
147 | var rgb = new Array();
148 | for(var i=0; i<3; i++){
149 | rgb.push(Math.ceil(Math.random()*150 + 50));
150 | }
151 | return 'rgb('+rgb.join(",")+')';
152 | }
153 |
154 | /*Set the chart's data in the format:
155 | *
156 | * {
157 | * "label-1": data-value-1,
158 | * "label-2": data-value-2,
159 | * "label-3": data-value-3,
160 | * ....
161 | * "label-N": data-value-N,
162 | * }
163 | *
164 | */
165 | this.setChartDataFromJSON = function(jsonObj){
166 | for(var p in jsonObj){
167 | this.labels.push(p);
168 | this.data.push(jsonObj[p]);
169 | }
170 | }
171 |
172 |
173 | this.draw = function(){
174 | var context = this.ctx;
175 | context.lineCap = 'round';
176 | var minFactor = Math.min(this.widthSizeFactor, this.heightSizeFactor);
177 |
178 | if(this.proportionalSizes){
179 | this.labelMargin = this.labelMargin * this.heightSizeFactor;
180 | this.dataValueMargin = this.dataValueMargin * this.heightSizeFactor;
181 | this.titleMargin = this.titleMargin * this.heightSizeFactor;
182 | this.yAxisLabelMargin = this.yAxisLabelMargin * this.heightSizeFactor;
183 |
184 | this.labelFontHeight = this.labelFontHeight * minFactor;
185 | this.dataValueFontHeight = this.dataValueFontHeight * minFactor;
186 | this.titleFontHeight = this.titleFontHeight * minFactor;
187 | this.yAxisLabelFontHeight = this.yAxisLabelFontHeight * minFactor;
188 |
189 | this.barHGap = this.barHGap * this.widthSizeFactor;
190 | this.barVGap = this.barHGap * this.heightSizeFactor;
191 | this.explosionOffset = this.explosionOffset * minFactor;
192 | }
193 |
194 | if(this.randomColors){
195 | for(var i=0; i=0){
354 | context.textBaseline = 'bottom';
355 | context.fillText(this.labels[i], x + barWidth/2, barBottomY - barHeight - this.labelMargin, barWidth);
356 | }else{
357 | context.textBaseline = 'top';
358 | context.fillText(this.labels[i], x + barWidth/2, barBottomY - barHeight + this.labelMargin, barWidth);
359 | }
360 | }
361 |
362 | //Draw the data value:
363 |
364 | context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont;
365 | context.fillStyle = this.dataValueFillStyle;
366 | context.textAlign = 'center';
367 | if(di>=0){
368 | context.textBaseline = 'bottom';
369 | context.fillText(di, x + barWidth/2, barBottomY - barHeight - this.labelMargin - this.dataValueMargin, barWidth);
370 | }else{
371 | context.textBaseline = 'top';
372 | context.fillText(di, x + barWidth/2, barBottomY - barHeight + this.labelMargin + this.dataValueMargin, barWidth);
373 | }
374 |
375 |
376 | //Update x:
377 |
378 | x = x + barWidth + this.barHGap;
379 | }
380 | }
381 |
382 |
383 |
384 | this.animateBarChart = function() {
385 | var aw = this,
386 | numFrames = this.animationFrames,
387 | currentFrame = 0,
388 |
389 | maxData = this.data.max(),
390 | minData = this.data.min(),
391 |
392 | barMaxTopY = this.marginTop + this.labelMargin + this.labelFontHeight + this.dataValueMargin + this.dataValueFontHeight,
393 | barMinTopY = barBottomY = this.height - this.marginBottom;
394 |
395 | if(this.title!=null){
396 | barMaxTopY += this.titleFontHeight + this.titleMargin;
397 | }
398 |
399 | if(minData<0){
400 | barMinTopY = this.height - this.marginBottom - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight;
401 |
402 | barBottomY = barMinTopY + ((this.height - this.marginBottom - barMaxTopY - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight) * minData) / (Math.abs(minData)+maxData);
403 | }
404 |
405 | var chartAreaHeight = barMinTopY - barMaxTopY,
406 | changeOfMarginBottom = 0,
407 | changeOfMarginTop = 0;
408 |
409 | var belowZeroMaxBarHeight = 0;
410 | if(minData<0){
411 | var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math.abs(barBottomY - barMinTopY)),
412 | maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData));
413 | belowZeroMaxBarHeight = Math.abs(minData * maxBarHeight / maxBarAbsData + this.labelMargin + this.labelFontHeight);
414 | }
415 |
416 | this.marginBottom += belowZeroMaxBarHeight;
417 | if(this.title!=null){
418 | this.titleMargin += chartAreaHeight - belowZeroMaxBarHeight;
419 | }else{
420 | this.marginTop += chartAreaHeight - belowZeroMaxBarHeight;
421 | }
422 | changeOfMarginBottom = belowZeroMaxBarHeight / numFrames;
423 | changeOfMarginTop = (chartAreaHeight - belowZeroMaxBarHeight) / numFrames;
424 |
425 | var updateBarChart = function() {
426 | if(currentFrame++ < numFrames) {
427 |
428 | aw.marginBottom -= changeOfMarginBottom;
429 |
430 | if(aw.title!=null){
431 | aw.titleMargin -= changeOfMarginTop;
432 | }else{
433 | aw.marginTop -= changeOfMarginTop;
434 | }
435 |
436 | aw.ctx.clearRect(0, 0, aw.width, aw.height);
437 | aw.drawBarChart();
438 | aw.drawTitleAndBorders();
439 |
440 | // Standard
441 | if (typeof(window.requestAnimationFrame) == 'function') {
442 | window.requestAnimationFrame(updateBarChart);
443 |
444 | // IE 10+
445 | } else if (typeof(window.msRequestAnimationFrame) == 'function') {
446 | window.msRequestAnimationFrame(updateBarChart);
447 |
448 | // Chrome
449 | } else if (typeof(window.webkitRequestAnimationFrame) == 'function') {
450 | window.webkitRequestAnimationFrame(updateBarChart);
451 |
452 | // Firefox
453 | } else if (window.mozRequestAnimationFrame) { // Seems rather slow in FF6 - so disabled
454 | window.mozRequestAnimationFrame(updateBarChart);
455 |
456 | // Default fallback to setTimeout
457 | } else {
458 | setTimeout(updateBarChart, 16.6666666);
459 | }
460 | }
461 | }
462 |
463 | updateBarChart();
464 |
465 | }
466 |
467 |
468 |
469 | this.drawVerticalBarChart = function(){
470 | var context = this.ctx;
471 |
472 | context.save();
473 | context.translate(this.width/2, this.height/2);
474 | context.rotate(Math.PI/2);
475 | context.translate(-this.width/2, -this.height/2);
476 |
477 | //Calculate bar size:
478 |
479 | var n = this.data.length;
480 | var maxData = this.data.max();
481 | var minData = this.data.min();
482 |
483 | var marginLeft = this.marginLeft;
484 | if(this.title!=null){
485 | marginLeft += this.titleFontHeight + this.titleMargin;
486 | }
487 |
488 | var barWidth = (this.width - marginLeft - this.marginRight - (n-1) * this.barHGap) / n;
489 |
490 | context.font = this.labelFontStyle + ' ' + this.labelFontHeight + 'px '+ this.labelFont;
491 | var maxLabelWidth = 0;
492 | var labelWidth = 0;
493 | for(var i=0; imaxLabelWidth){
496 | maxLabelWidth = labelWidth;
497 | }
498 | }
499 |
500 | context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont;
501 | var maxDataValueWidth = 0;
502 | var dataValueWidth = 0;
503 | for(var i=0; imaxDataValueWidth){
506 | maxDataValueWidth = dataValueWidth;
507 | }
508 | }
509 |
510 | var barMaxTopY = this.marginTop + Math.max( (this.labelMargin + maxLabelWidth), (this.dataValueMargin + maxDataValueWidth) );
511 |
512 | var barMinTopY = this.height - this.marginBottom;
513 |
514 | var barBottomY = this.height - this.marginBottom;
515 |
516 | if(minData<0){
517 |
518 | barMinTopY = this.height - this.marginBottom - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight;
519 |
520 | barBottomY = barMinTopY + ((this.height - this.marginBottom - barMaxTopY - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight) * minData) / (Math.abs(minData)+maxData);
521 |
522 | }
523 |
524 |
525 | var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math.abs(barBottomY - barMinTopY));
526 | var maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData));
527 |
528 | var x = marginLeft;
529 | var y = barBottomY;
530 | var barHeight = 0;
531 |
532 | var di = 0;
533 |
534 | for(var i=0; i=0){
581 | context.textAlign = 'left';
582 | context.fillText(this.labels[i], this.labelMargin, 0);
583 | }else{
584 | context.textAlign = 'right';
585 | context.fillText(this.labels[i], -this.labelMargin, 0);
586 | }
587 | }
588 |
589 | //Draw the data value:
590 |
591 | context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont;
592 | context.fillStyle = this.dataValueFillStyle;
593 | context.textBaseline = 'bottom';
594 | if(di>=0){
595 | context.textAlign = 'left';
596 | context.fillText(di, this.labelMargin, 0);
597 | }else{
598 | context.textAlign = 'right';
599 | context.fillText(di, -this.labelMargin, 0);
600 | }
601 |
602 | context.restore();
603 |
604 | //Update x:
605 |
606 | x = x + barWidth + this.barHGap;
607 | }
608 |
609 | context.restore();
610 |
611 | }
612 |
613 |
614 |
615 | this.animateVerticalBarChart = function() {
616 | var aw = this,
617 | numFrames = this.animationFrames,
618 | currentFrame = 0,
619 |
620 | maxData = this.data.max(),
621 | minData = this.data.min(),
622 | dataLen = this.data.length,
623 |
624 | context = this.ctx,
625 |
626 | marginLeft = this.marginLeft
627 | marginTop = this.marginTop
628 | marginTopCurrent = 0;
629 |
630 |
631 | if(this.title!=null){
632 | marginLeft += this.titleFontHeight + this.titleMargin;
633 | }
634 |
635 | var barWidth = (this.width - marginLeft - this.marginRight - (dataLen-1) * this.barHGap) / dataLen;
636 |
637 | context.font = this.labelFontStyle + ' ' + this.labelFontHeight + 'px '+ this.labelFont;
638 | var maxLabelWidth = 0;
639 | var labelWidth = 0;
640 | for(var i=0; imaxLabelWidth){
643 | maxLabelWidth = labelWidth;
644 | }
645 | }
646 |
647 | context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont;
648 | var maxDataValueWidth = 0;
649 | var dataValueWidth = 0;
650 | for(var i=0; imaxDataValueWidth){
653 | maxDataValueWidth = dataValueWidth;
654 | }
655 | }
656 |
657 | var barMaxTopY = this.marginTop + Math.max( (this.labelMargin + maxLabelWidth), (this.dataValueMargin + maxDataValueWidth) );
658 |
659 | var barMinTopY = this.height - this.marginBottom;
660 |
661 | var barBottomY = this.height - this.marginBottom;
662 |
663 | if(minData<0){
664 |
665 | barMinTopY = this.height - this.marginBottom - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight;
666 |
667 | barBottomY = barMinTopY + ((this.height - this.marginBottom - barMaxTopY - this.labelMargin - this.labelFontHeight - this.dataValueMargin - this.dataValueFontHeight) * minData) / (Math.abs(minData)+maxData);
668 |
669 | }
670 |
671 |
672 | var maxBarHeight = Math.max(Math.abs(barBottomY - barMaxTopY), Math.abs(barBottomY - barMinTopY));
673 | var maxBarAbsData = Math.max(Math.abs(minData), Math.abs(maxData));
674 |
675 |
676 | var belowZeroMaxBarHeight = 0;
677 | if(minData<0){
678 | belowZeroMaxBarHeight = Math.abs(minData * maxBarHeight / maxBarAbsData);
679 | }
680 |
681 | var chartAreaHeight = maxData * maxBarHeight / maxBarAbsData + belowZeroMaxBarHeight,
682 | changeOfMarginBottom = 0,
683 | changeOfMarginTop = 0;
684 |
685 | this.marginBottom += belowZeroMaxBarHeight;
686 | this.marginTop += chartAreaHeight - belowZeroMaxBarHeight;
687 | changeOfMarginBottom = belowZeroMaxBarHeight / numFrames;
688 | changeOfMarginTop = (chartAreaHeight - belowZeroMaxBarHeight) / numFrames;
689 |
690 | var updateVerticalBarChart = function() {
691 | if(currentFrame++ < numFrames) {
692 |
693 | aw.marginBottom -= changeOfMarginBottom;
694 | aw.marginTop -= changeOfMarginTop;
695 |
696 | aw.ctx.clearRect(0, 0, aw.width, aw.height);
697 | aw.drawVerticalBarChart();
698 |
699 | marginTopCurrent = aw.marginTop;
700 | aw.marginTop = marginTop;
701 | aw.drawTitleAndBorders();
702 | aw.marginTop = marginTopCurrent;
703 |
704 | // Standard
705 | if (typeof(window.requestAnimationFrame) == 'function') {
706 | window.requestAnimationFrame(updateVerticalBarChart);
707 |
708 | // IE 10+
709 | } else if (typeof(window.msRequestAnimationFrame) == 'function') {
710 | window.msRequestAnimationFrame(updateVerticalBarChart);
711 |
712 | // Chrome
713 | } else if (typeof(window.webkitRequestAnimationFrame) == 'function') {
714 | window.webkitRequestAnimationFrame(updateVerticalBarChart);
715 |
716 | // Firefox
717 | } else if (window.mozRequestAnimationFrame) { // Seems rather slow in FF6 - so disabled
718 | window.mozRequestAnimationFrame(updateVerticalBarChart);
719 |
720 | // Default fallback to setTimeout
721 | } else {
722 | setTimeout(updateVerticalBarChart, 16.6666666);
723 | }
724 | }
725 | }
726 |
727 | updateVerticalBarChart();
728 |
729 | }
730 |
731 |
732 |
733 | this.drawPieChart = function(ring){
734 | var context = this.ctx;
735 | context.lineWidth = this.pieBorderWidth;
736 |
737 | var dataSum = 0,
738 | dataSumForStartAngle = 0,
739 | dataLen = this.data.length;
740 |
741 | for (var i=0; imaxLabelWidth){
776 | maxLabelWidth = labelWidth;
777 | }
778 | }
779 |
780 | radius = radius - maxLabelWidth - this.labelMargin;
781 |
782 | var startAngle = this.pieStart* doublePI / dataSumForStartAngle;
783 | var currentAngle = startAngle;
784 | var endAngle = 0;
785 | var incAngleBy = 0;
786 |
787 | for(var i=0; iMath.PI/2) && (mAngle<=3*(Math.PI/2)) ){
910 | var translateXBy = radius + this.labelMargin + context.measureText(this.labels[i]).width / 2;
911 | context.translate(translateXBy, 0);
912 | context.rotate(Math.PI);
913 | context.translate(-translateXBy, 0);
914 | }
915 | context.textBaseline = 'middle';
916 | context.fillText(this.labels[i], radius+this.labelMargin, 0);
917 | }
918 |
919 | context.restore();
920 | currentAngle = endAngle;
921 | }
922 | }
923 |
924 |
925 |
926 | this.drawExplodedPieChart = function(){
927 | var context = this.ctx;
928 | context.lineWidth = this.pieBorderWidth;
929 |
930 | var dataSum = 0,
931 | dataSumForStartAngle = 0,
932 | dataLen = this.data.length;
933 |
934 | for (var i=0; imaxLabelWidth){
969 | maxLabelWidth = labelWidth;
970 | }
971 | }
972 |
973 | radius = radius - maxLabelWidth - this.labelMargin;
974 |
975 | var currentAngle = this.pieStart* doublePI / dataSumForStartAngle;
976 | var endAngle = 0;
977 | var incAngleBy = 0;
978 | var halfAngle = 0;
979 | var mAngle = 0;
980 | for(var i=0; iMath.PI/2) && (mAngle<=3*(Math.PI/2)) ){
1033 | var translateXBy = radius + this.labelMargin + context.measureText(this.labels[i]).width / 2;
1034 | context.translate(translateXBy, 0);
1035 | context.rotate(Math.PI);
1036 | context.translate(-translateXBy, 0);
1037 | }
1038 | context.textBaseline = 'middle';
1039 | context.fillText(this.labels[i], radius+this.labelMargin, 0);
1040 | }
1041 |
1042 |
1043 | // Restore the context:
1044 |
1045 | context.restore();
1046 | currentAngle = endAngle;
1047 |
1048 | }
1049 |
1050 | }
1051 |
1052 |
1053 |
1054 | this.animatePieChart = function(pieType){
1055 | var dataSum = 0,
1056 | pieTotalReal = this.pieTotal,
1057 | aw = this,
1058 | numFrames = this.animationFrames,
1059 | currentFrame = 0,
1060 | pieAreaWidth = this.width - this.marginLeft - this.marginRight,
1061 | pieAreaHeight = this.height - this.marginTop - this.marginBottom,
1062 | marginTop = this.marginTop,
1063 | marginLeft = this.marginLeft;
1064 |
1065 | if(this.title){
1066 | pieAreaHeight = pieAreaHeight - this.titleFontHeight - this.titleMargin;
1067 | marginTop += this.titleFontHeight + this.titleMargin;
1068 | };
1069 |
1070 | for(var i=0; imaxYAxisLabelWidth){
1165 | maxYAxisLabelWidth = yAxisLabelWidth;
1166 | }
1167 | }
1168 |
1169 | var perCentMaxWidth = context.measureText("100%").width;
1170 |
1171 | // Calculate the chart size and position:
1172 |
1173 | var chartWidth = this.width - this.marginLeft - this.marginRight - 2*this.chartMarkerSize - maxYAxisLabelWidth - perCentMaxWidth - 2*this.yAxisLabelMargin;
1174 | var chartHeight = this.height - this.marginTop - this.marginBottom;
1175 |
1176 | var chartTopLeftX = this.marginLeft + this.chartMarkerSize + maxYAxisLabelWidth + this.yAxisLabelMargin;
1177 | var chartTopLeftY = this.marginTop;
1178 |
1179 |
1180 | if(this.title){
1181 | chartHeight -= this.titleFontHeight + this.titleMargin;
1182 | chartTopLeftY += this.titleFontHeight + this.titleMargin;
1183 | }
1184 |
1185 |
1186 | // Draw the chart's background:
1187 |
1188 | context.save();
1189 |
1190 | context.translate(chartTopLeftX, chartTopLeftY);
1191 |
1192 | context.fillStyle = this.chartBackgroundFillStyle;
1193 | context.fillRect(0,0,chartWidth,chartHeight);
1194 |
1195 |
1196 | // Draw the markers, horizontal lines, and axis' labels:
1197 |
1198 | var yStep = chartHeight / 10;
1199 | var lineY = 0;
1200 |
1201 | context.lineWidth = this.chartHorizontalLineWidth;
1202 | context.font = this.yAxisLabelFontStyle + ' ' + this.yAxisLabelFontHeight + 'px '+ this.yAxisLabelFont;
1203 |
1204 | for(var i=0; i<=10; i++){
1205 | lineY = i*yStep;
1206 |
1207 | if( i>0 && i<10){
1208 |
1209 | context.strokeStyle = this.chartHorizontalLineStrokeStyle;
1210 | context.beginPath();
1211 | context.moveTo(0,lineY);
1212 | context.lineTo(chartWidth,lineY);
1213 | context.stroke();
1214 |
1215 | }
1216 |
1217 | context.strokeStyle = this.chartBorderStrokeStyle;
1218 | context.beginPath();
1219 | context.moveTo(-this.chartMarkerSize,lineY);
1220 | context.lineTo(0,lineY);
1221 | context.stroke();
1222 |
1223 | context.beginPath();
1224 | context.moveTo(chartWidth,lineY);
1225 | context.lineTo(chartWidth+this.chartMarkerSize,lineY);
1226 | context.stroke();
1227 |
1228 | context.fillStyle = this.yAxisLabelFillStyle;
1229 | context.textAlign = 'right';
1230 | context.textBaseline = 'middle';
1231 | context.fillText(yAxisValues[10-i], -this.chartMarkerSize-this.yAxisLabelMargin, lineY);
1232 |
1233 | context.textAlign = 'left';
1234 | context.fillText( ((10-i)*10)+'%', chartWidth+this.chartMarkerSize+this.yAxisLabelMargin, lineY);
1235 | }
1236 |
1237 | // Draw the bars:
1238 |
1239 | context.save();
1240 |
1241 | context.translate(0, chartHeight);
1242 |
1243 | var barWidth = (chartWidth-2*this.barHGap) / n;
1244 | var barHeight = 0;
1245 |
1246 | var halfBarWidth = barWidth/2;
1247 |
1248 | var y = 0;
1249 | var x = this.barHGap;
1250 | var x1 = x;
1251 | var y1 = 0;
1252 | var x2 = 0;
1253 | var y2 = 0;
1254 |
1255 | for(var i=0; i=0){
1315 | context.textBaseline = 'bottom';
1316 | context.fillText(this.labels[indices[i]], x + halfBarWidth, - barHeight - this.labelMargin, barWidth);
1317 | }else{
1318 | context.textBaseline = 'top';
1319 | context.fillText(this.labels[indices[i]], x + halfBarWidth, - barHeight + this.labelMargin, barWidth);
1320 | }
1321 | }
1322 |
1323 | // Draw the data value:
1324 |
1325 | context.font = this.dataValueFontStyle + ' ' + this.dataValueFontHeight + 'px '+ this.dataValueFont;
1326 | context.fillStyle = this.dataValueFillStyle;
1327 | context.textAlign = 'center';
1328 | if(this.data[indices[i]]>=0){
1329 | context.textBaseline = 'bottom';
1330 | context.fillText(this.data[indices[i]], x + halfBarWidth, - barHeight - this.labelMargin - this.dataValueMargin, barWidth);
1331 | }else{
1332 | context.textBaseline = 'top';
1333 | context.fillText(this.data[indices[i]], x + halfBarWidth, - barHeight + this.labelMargin + this.dataValueMargin, barWidth);
1334 | }
1335 |
1336 |
1337 | // Update x:
1338 |
1339 | x = x + barWidth;
1340 |
1341 | }
1342 |
1343 | // Draw the points:
1344 |
1345 | x = this.barHGap;
1346 | x1 = x;
1347 | y1 = 0;
1348 | x2 = 0;
1349 | y2 = 0;
1350 |
1351 | context.fillStyle = this.chartPointFillStyle;
1352 | context.beginPath();
1353 | context.arc(x1, y1, this.chartPointRadius, 0, 2*Math.PI, false);
1354 | context.fill();
1355 |
1356 | for(var i=0; i