6 helpers = Chart.helpers;
13 //Boolean - Whether to show lines for each scale point
16 //Boolean - Whether we show the angle lines out of the radar
17 angleShowLineOut : true,
19 //Boolean - Whether to show labels on the scale
20 scaleShowLabels : false,
22 // Boolean - Whether the scale should begin at zero
23 scaleBeginAtZero : true,
25 //String - Colour of the angle line
26 angleLineColor : "rgba(0,0,0,.1)",
28 //Number - Pixel width of the angle line
31 //String - Point label font declaration
32 pointLabelFontFamily : "'Arial'",
34 //String - Point label font weight
35 pointLabelFontStyle : "normal",
37 //Number - Point label font size in pixels
38 pointLabelFontSize : 10,
40 //String - Point label font colour
41 pointLabelFontColor : "#666",
43 //Boolean - Whether to show a dot for each point
46 //Number - Radius of each point dot in pixels
49 //Number - Pixel width of point dot stroke
50 pointDotStrokeWidth : 1,
52 //Number - amount extra to add to the radius to cater for hit detection outside the drawn point
53 pointHitDetectionRadius : 20,
55 //Boolean - Whether to show a stroke for datasets
58 //Number - Pixel width of dataset stroke
59 datasetStrokeWidth : 2,
61 //Boolean - Whether to fill the dataset with a colour
64 //String - A legend template
65 legendTemplate : "<ul class=\"<%=name.toLowerCase()%>-legend\"><% for (var i=0; i<datasets.length; i++){%><li><span style=\"background-color:<%=datasets[i].strokeColor%>\"><%if(datasets[i].label){%><%=datasets[i].label%><%}%></span></li><%}%></ul>"
69 initialize: function(data){
70 this.PointClass = Chart.Point.extend({
71 strokeWidth : this.options.pointDotStrokeWidth,
72 radius : this.options.pointDotRadius,
73 display: this.options.pointDot,
74 hitDetectionRadius : this.options.pointHitDetectionRadius,
80 this.buildScale(data);
82 //Set up tooltip events on the chart
83 if (this.options.showTooltips){
84 helpers.bindEvents(this, this.options.tooltipEvents, function(evt){
85 var activePointsCollection = (evt.type !== 'mouseout') ? this.getPointsAtEvent(evt) : [];
87 this.eachPoints(function(point){
88 point.restore(['fillColor', 'strokeColor']);
90 helpers.each(activePointsCollection, function(activePoint){
91 activePoint.fillColor = activePoint.highlightFill;
92 activePoint.strokeColor = activePoint.highlightStroke;
95 this.showTooltip(activePointsCollection);
99 //Iterate through each of the datasets, and build this into a property of the chart
100 helpers.each(data.datasets,function(dataset){
102 var datasetObject = {
103 label: dataset.label || null,
104 fillColor : dataset.fillColor,
105 strokeColor : dataset.strokeColor,
106 pointColor : dataset.pointColor,
107 pointStrokeColor : dataset.pointStrokeColor,
111 this.datasets.push(datasetObject);
113 helpers.each(dataset.data,function(dataPoint,index){
114 //Add a new point for each piece of data, passing any required data to draw.
116 if (!this.scale.animation){
117 pointPosition = this.scale.getPointPosition(index, this.scale.calculateCenterOffset(dataPoint));
119 datasetObject.points.push(new this.PointClass({
121 label : data.labels[index],
122 datasetLabel: dataset.label,
123 x: (this.options.animation) ? this.scale.xCenter : pointPosition.x,
124 y: (this.options.animation) ? this.scale.yCenter : pointPosition.y,
125 strokeColor : dataset.pointStrokeColor,
126 fillColor : dataset.pointColor,
127 highlightFill : dataset.pointHighlightFill || dataset.pointColor,
128 highlightStroke : dataset.pointHighlightStroke || dataset.pointStrokeColor
136 eachPoints : function(callback){
137 helpers.each(this.datasets,function(dataset){
138 helpers.each(dataset.points,callback,this);
142 getPointsAtEvent : function(evt){
143 var mousePosition = helpers.getRelativePosition(evt),
144 fromCenter = helpers.getAngleFromPoint({
145 x: this.scale.xCenter,
146 y: this.scale.yCenter
149 var anglePerIndex = (Math.PI * 2) /this.scale.valuesCount,
150 pointIndex = Math.round((fromCenter.angle - Math.PI * 1.5) / anglePerIndex),
151 activePointsCollection = [];
153 // If we're at the top, make the pointIndex 0 to get the first of the array.
154 if (pointIndex >= this.scale.valuesCount || pointIndex < 0){
158 if (fromCenter.distance <= this.scale.drawingArea){
159 helpers.each(this.datasets, function(dataset){
160 activePointsCollection.push(dataset.points[pointIndex]);
164 return activePointsCollection;
167 buildScale : function(data){
168 this.scale = new Chart.RadialScale({
169 display: this.options.showScale,
170 fontStyle: this.options.scaleFontStyle,
171 fontSize: this.options.scaleFontSize,
172 fontFamily: this.options.scaleFontFamily,
173 fontColor: this.options.scaleFontColor,
174 showLabels: this.options.scaleShowLabels,
175 showLabelBackdrop: this.options.scaleShowLabelBackdrop,
176 backdropColor: this.options.scaleBackdropColor,
177 backdropPaddingY : this.options.scaleBackdropPaddingY,
178 backdropPaddingX: this.options.scaleBackdropPaddingX,
179 lineWidth: (this.options.scaleShowLine) ? this.options.scaleLineWidth : 0,
180 lineColor: this.options.scaleLineColor,
181 angleLineColor : this.options.angleLineColor,
182 angleLineWidth : (this.options.angleShowLineOut) ? this.options.angleLineWidth : 0,
183 // Point labels at the edge of each line
184 pointLabelFontColor : this.options.pointLabelFontColor,
185 pointLabelFontSize : this.options.pointLabelFontSize,
186 pointLabelFontFamily : this.options.pointLabelFontFamily,
187 pointLabelFontStyle : this.options.pointLabelFontStyle,
188 height : this.chart.height,
189 width: this.chart.width,
190 xCenter: this.chart.width/2,
191 yCenter: this.chart.height/2,
192 ctx : this.chart.ctx,
193 templateString: this.options.scaleLabel,
195 valuesCount: data.datasets[0].data.length
198 this.scale.setScaleSize();
199 this.updateScaleRange(data.datasets);
200 this.scale.buildYLabels();
202 updateScaleRange: function(datasets){
203 var valuesArray = (function(){
204 var totalDataArray = [];
205 helpers.each(datasets,function(dataset){
207 totalDataArray = totalDataArray.concat(dataset.data);
210 helpers.each(dataset.points, function(point){
211 totalDataArray.push(point.value);
215 return totalDataArray;
219 var scaleSizes = (this.options.scaleOverride) ?
221 steps: this.options.scaleSteps,
222 stepValue: this.options.scaleStepWidth,
223 min: this.options.scaleStartValue,
224 max: this.options.scaleStartValue + (this.options.scaleSteps * this.options.scaleStepWidth)
226 helpers.calculateScaleRange(
228 helpers.min([this.chart.width, this.chart.height])/2,
229 this.options.scaleFontSize,
230 this.options.scaleBeginAtZero,
231 this.options.scaleIntegersOnly
240 addData : function(valuesArray,label){
241 //Map the values array for each of the datasets
242 this.scale.valuesCount++;
243 helpers.each(valuesArray,function(value,datasetIndex){
244 var pointPosition = this.scale.getPointPosition(this.scale.valuesCount, this.scale.calculateCenterOffset(value));
245 this.datasets[datasetIndex].points.push(new this.PointClass({
248 datasetLabel: this.datasets[datasetIndex].label,
251 strokeColor : this.datasets[datasetIndex].pointStrokeColor,
252 fillColor : this.datasets[datasetIndex].pointColor
256 this.scale.labels.push(label);
262 removeData : function(){
263 this.scale.valuesCount--;
264 this.scale.labels.shift();
265 helpers.each(this.datasets,function(dataset){
266 dataset.points.shift();
272 this.eachPoints(function(point){
279 helpers.extend(this.scale, {
280 width : this.chart.width,
281 height: this.chart.height,
282 size : helpers.min([this.chart.width, this.chart.height]),
283 xCenter: this.chart.width/2,
284 yCenter: this.chart.height/2
286 this.updateScaleRange(this.datasets);
287 this.scale.setScaleSize();
288 this.scale.buildYLabels();
290 draw : function(ease){
291 var easeDecimal = ease || 1,
292 ctx = this.chart.ctx;
296 helpers.each(this.datasets,function(dataset){
298 //Transition each point first so that the line and point drawing isn't out of sync
299 helpers.each(dataset.points,function(point,index){
300 if (point.hasValue()){
301 point.transition(this.scale.getPointPosition(index, this.scale.calculateCenterOffset(point.value)), easeDecimal);
307 //Draw the line between all the points
308 ctx.lineWidth = this.options.datasetStrokeWidth;
309 ctx.strokeStyle = dataset.strokeColor;
311 helpers.each(dataset.points,function(point,index){
313 ctx.moveTo(point.x,point.y);
316 ctx.lineTo(point.x,point.y);
322 ctx.fillStyle = dataset.fillColor;
323 if(this.options.datasetFill){
326 //Now draw the points over the line
327 //A little inefficient double looping, but better than the line
328 //lagging behind the point positions
329 helpers.each(dataset.points,function(point){
330 if (point.hasValue()){