6 //Cache a local reference to Chart.helpers
7 helpers = Chart.helpers;
10 //Boolean - Show a backdrop to the scale label
11 scaleShowLabelBackdrop : true,
13 //String - The colour of the label backdrop
14 scaleBackdropColor : "rgba(255,255,255,0.75)",
16 // Boolean - Whether the scale should begin at zero
17 scaleBeginAtZero : true,
19 //Number - The backdrop padding above & below the label in pixels
20 scaleBackdropPaddingY : 2,
22 //Number - The backdrop padding to the side of the label in pixels
23 scaleBackdropPaddingX : 2,
25 //Boolean - Show line for each value in the scale
28 //Boolean - Stroke a line around each segment in the chart
29 segmentShowStroke : true,
31 //String - The colour of the stroke on each segment.
32 segmentStrokeColor : "#fff",
34 //Number - The width of the stroke value in pixels
35 segmentStrokeWidth : 2,
37 //Number - Amount of animation steps
40 //String - Animation easing effect.
41 animationEasing : "easeOutBounce",
43 //Boolean - Whether to animate the rotation of the chart
46 //Boolean - Whether to animate scaling the chart from the centre
49 //String - A legend template
50 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<segments.length; i++){%><li><span style=\"background-color:<%=segments[i].fillColor%>\"><%if(segments[i].label){%><%=segments[i].label%><%}%></span></li><%}%></ul>"
55 //Passing in a name registers this chart in the Chart namespace
57 //Providing a defaults will also register the deafults in the chart namespace
58 defaults : defaultConfig,
59 //Initialize is fired when the chart is initialized - Data is passed in as a parameter
60 //Config is automatically merged by the core of Chart.js, and is available at this.options
61 initialize: function(data){
63 //Declare segment class as a chart instance specific class, so it can share props for this instance
64 this.SegmentArc = Chart.Arc.extend({
65 showStroke : this.options.segmentShowStroke,
66 strokeWidth : this.options.segmentStrokeWidth,
67 strokeColor : this.options.segmentStrokeColor,
70 x : this.chart.width/2,
71 y : this.chart.height/2
73 this.scale = new Chart.RadialScale({
74 display: this.options.showScale,
75 fontStyle: this.options.scaleFontStyle,
76 fontSize: this.options.scaleFontSize,
77 fontFamily: this.options.scaleFontFamily,
78 fontColor: this.options.scaleFontColor,
79 showLabels: this.options.scaleShowLabels,
80 showLabelBackdrop: this.options.scaleShowLabelBackdrop,
81 backdropColor: this.options.scaleBackdropColor,
82 backdropPaddingY : this.options.scaleBackdropPaddingY,
83 backdropPaddingX: this.options.scaleBackdropPaddingX,
84 lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
85 lineColor: this.options.scaleLineColor,
87 width: this.chart.width,
88 height: this.chart.height,
89 xCenter: this.chart.width/2,
90 yCenter: this.chart.height/2,
92 templateString: this.options.scaleLabel,
93 valuesCount: data.length
96 this.updateScaleRange(data);
100 helpers.each(data,function(segment,index){
101 this.addData(segment,index,true);
104 //Set up tooltip events on the chart
105 if (this.options.showTooltips){
106 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
107 var activeSegments = (evt.type !== 'mouseout') ? this.getSegmentsAtEvent(evt) : [];
108 helpers.each(this.segments,function(segment){
109 segment.restore(["fillColor"]);
111 helpers.each(activeSegments,function(activeSegment){
112 activeSegment.fillColor = activeSegment.highlightColor;
114 this.showTooltip(activeSegments);
120 getSegmentsAtEvent : function(e){
121 var segmentsArray = [];
123 var location = helpers.getRelativePosition(e);
125 helpers.each(this.segments,function(segment){
126 if (segment.inRange(location.x,location.y)) segmentsArray.push(segment);
128 return segmentsArray;
130 addData : function(segment, atIndex, silent){
131 var index = atIndex || this.segments.length;
133 this.segments.splice(index, 0, new this.SegmentArc({
134 fillColor: segment.color,
135 highlightColor: segment.highlight || segment.color,
136 label: segment.label,
137 value: segment.value,
138 outerRadius: (this.options.animateScale) ? 0 : this.scale.calculateCenterOffset(segment.value),
139 circumference: (this.options.animateRotate) ? 0 : this.scale.getCircumference(),
140 startAngle: Math.PI * 1.5
147 removeData: function(atIndex){
148 var indexToDelete = (helpers.isNumber(atIndex)) ? atIndex : this.segments.length-1;
149 this.segments.splice(indexToDelete, 1);
153 calculateTotal: function(data){
155 helpers.each(data,function(segment){
156 this.total += segment.value;
158 this.scale.valuesCount = this.segments.length;
160 updateScaleRange: function(datapoints){
161 var valuesArray = [];
162 helpers.each(datapoints,function(segment){
163 valuesArray.push(segment.value);
166 var scaleSizes = (this.options.scaleOverride) ?
168 steps: this.options.scaleSteps,
169 stepValue: this.options.scaleStepWidth,
170 min: this.options.scaleStartValue,
171 max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
173 helpers.calculateScaleRange(
175 helpers.min([this.chart.width, this.chart.height])/2,
176 this.options.scaleFontSize,
177 this.options.scaleBeginAtZero,
178 this.options.scaleIntegersOnly
185 size: helpers.min([this.chart.width, this.chart.height]),
186 xCenter: this.chart.width/2,
187 yCenter: this.chart.height/2
193 this.calculateTotal(this.segments);
195 helpers.each(this.segments,function(segment){
203 helpers.extend(this.SegmentArc.prototype,{
204 x : this.chart.width/2,
205 y : this.chart.height/2
207 this.updateScaleRange(this.segments);
210 helpers.extend(this.scale,{
211 xCenter: this.chart.width/2,
212 yCenter: this.chart.height/2
215 helpers.each(this.segments, function(segment){
217 outerRadius : this.scale.calculateCenterOffset(segment.value)
222 draw : function(ease){
223 var easingDecimal = ease || 1;
224 //Clear & draw the canvas
226 helpers.each(this.segments,function(segment, index){
228 circumference : this.scale.getCircumference(),
229 outerRadius : this.scale.calculateCenterOffset(segment.value)
232 segment.endAngle = segment.startAngle + segment.circumference;
234 // If we've removed the first segment we need to set the first one to
237 segment.startAngle = Math.PI * 1.5;
240 //Check to see if it's the last segment, if not get the next and update the start angle
241 if (index < this.segments.length - 1){
242 this.segments[index+1].startAngle = segment.endAngle;