(function() { "use strict"; var root = this, Chart = root.Chart, helpers = Chart.helpers; Chart.defaults.radar = { scale: { type: "radialLinear", }, elements: { line: { tension: 0, // no bezier in radar } }, }; Chart.controllers.radar = function(chart, datasetIndex) { this.initialize.call(this, chart, datasetIndex); }; helpers.extend(Chart.controllers.radar.prototype, { initialize: function(chart, datasetIndex) { this.chart = chart; this.index = datasetIndex; this.linkScales(); this.addElements(); }, updateIndex: function(datasetIndex) { this.index = datasetIndex; }, linkScales: function() { // No need. Single scale only }, getDataset: function() { return this.chart.data.datasets[this.index]; }, getScaleForId: function(scaleID) { return this.chart.scales[scaleID]; }, addElements: function() { this.getDataset().metaData = this.getDataset().metaData || []; this.getDataset().metaDataset = this.getDataset().metaDataset || new Chart.elements.Line({ _chart: this.chart.chart, _datasetIndex: this.index, _points: this.getDataset().metaData, _loop: true }); helpers.each(this.getDataset().data, function(value, index) { this.getDataset().metaData[index] = this.getDataset().metaData[index] || new Chart.elements.Point({ _chart: this.chart.chart, _datasetIndex: this.index, _index: index, _model: { x: 0, //xScale.getPixelForValue(null, index, true), y: 0, //this.chartArea.bottom, }, }); }, this); }, addElementAndReset: function(index) { this.getDataset().metaData = this.getDataset().metaData || []; var point = new Chart.elements.Point({ _chart: this.chart.chart, _datasetIndex: this.index, _index: index, }); // Reset the point this.updateElement(point, index, true); // Add to the points array this.getDataset().metaData.splice(index, 0, point); // Make sure bezier control points are updated this.updateBezierControlPoints(); }, removeElement: function(index) { this.getDataset().metaData.splice(index, 1); }, reset: function() { this.update(true); }, buildOrUpdateElements: function buildOrUpdateElements() { // Handle the number of data points changing var numData = this.getDataset().data.length; var numPoints = this.getDataset().metaData.length; // Make sure that we handle number of datapoints changing if (numData < numPoints) { // Remove excess bars for data points that have been removed this.getDataset().metaData.splice(numData, numPoints - numData); } else if (numData > numPoints) { // Add new elements for (var index = numPoints; index < numData; ++index) { this.addElementAndReset(index); } } }, update: function update(reset) { var line = this.getDataset().metaDataset; var points = this.getDataset().metaData; var scale = this.chart.scale; var scaleBase; if (scale.min < 0 && scale.max < 0) { scaleBase = scale.getPointPositionForValue(0, scale.max); } else if (scale.min > 0 && scale.max > 0) { scaleBase = scale.getPointPositionForValue(0, scale.min); } else { scaleBase = scale.getPointPositionForValue(0, 0); } helpers.extend(this.getDataset().metaDataset, { // Utility _datasetIndex: this.index, // Data _children: this.getDataset().metaData, // Model _model: { // Appearance tension: helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension), backgroundColor: this.getDataset().backgroundColor || this.chart.options.elements.line.backgroundColor, borderWidth: this.getDataset().borderWidth || this.chart.options.elements.line.borderWidth, borderColor: this.getDataset().borderColor || this.chart.options.elements.line.borderColor, fill: this.getDataset().fill !== undefined ? this.getDataset().fill : this.chart.options.elements.line.fill, // use the value from the this.getDataset() if it was provided. else fall back to the default // Scale scaleTop: scale.top, scaleBottom: scale.bottom, scaleZero: scaleBase, }, }); this.getDataset().metaDataset.pivot(); // Update Points helpers.each(points, function(point, index) { this.updateElement(point, index, reset); }, this); // Update bezier control points this.updateBezierControlPoints(); }, updateElement: function(point, index, reset) { var pointPosition = this.chart.scale.getPointPositionForValue(index, this.getDataset().data[index]); helpers.extend(point, { // Utility _datasetIndex: this.index, _index: index, _scale: this.chart.scale, // Desired view properties _model: { x: reset ? this.chart.scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales y: reset ? this.chart.scale.yCenter : pointPosition.y, // Appearance tension: point.custom && point.custom.tension ? point.custom.tension : helpers.getValueOrDefault(this.getDataset().tension, this.chart.options.elements.line.tension), radius: point.custom && point.custom.radius ? point.custom.pointRadius : helpers.getValueAtIndexOrDefault(this.getDataset().pointRadius, index, this.chart.options.elements.point.radius), backgroundColor: point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor), borderColor: point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor), borderWidth: point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth), // Tooltip hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius), }, }); point._model.skip = point.custom && point.custom.skip ? point.custom.skip : (isNaN(point._model.x) || isNaN(point._model.y)); }, updateBezierControlPoints: function() { helpers.each(this.getDataset().metaData, function(point, index) { var controlPoints = helpers.splineCurve( helpers.previousItem(this.getDataset().metaData, index, true)._model, point._model, helpers.nextItem(this.getDataset().metaData, index, true)._model, point._model.tension ); // Prevent the bezier going outside of the bounds of the graph point._model.controlPointPreviousX = Math.max(Math.min(controlPoints.previous.x, this.chart.chartArea.right), this.chart.chartArea.left); point._model.controlPointPreviousY = Math.max(Math.min(controlPoints.previous.y, this.chart.chartArea.bottom), this.chart.chartArea.top); point._model.controlPointNextX = Math.max(Math.min(controlPoints.next.x, this.chart.chartArea.right), this.chart.chartArea.left); point._model.controlPointNextY = Math.max(Math.min(controlPoints.next.y, this.chart.chartArea.bottom), this.chart.chartArea.top); // Now pivot the point for animation point.pivot(); }, this); }, draw: function(ease) { var easingDecimal = ease || 1; // Transition Point Locations helpers.each(this.getDataset().metaData, function(point, index) { point.transition(easingDecimal); }, this); // Transition and Draw the line this.getDataset().metaDataset.transition(easingDecimal).draw(); // Draw the points helpers.each(this.getDataset().metaData, function(point) { point.draw(); }); }, setHoverStyle: function(point) { // Point var dataset = this.chart.data.datasets[point._datasetIndex]; var index = point._index; point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(dataset.pointHoverRadius, index, this.chart.options.elements.point.hoverRadius); point._model.backgroundColor = point.custom && point.custom.hoverBackgroundColor ? point.custom.hoverBackgroundColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBackgroundColor, index, helpers.color(point._model.backgroundColor).saturate(0.5).darken(0.1).rgbString()); point._model.borderColor = point.custom && point.custom.hoverBorderColor ? point.custom.hoverBorderColor : helpers.getValueAtIndexOrDefault(dataset.pointHoverBorderColor, index, helpers.color(point._model.borderColor).saturate(0.5).darken(0.1).rgbString()); point._model.borderWidth = point.custom && point.custom.hoverBorderWidth ? point.custom.hoverBorderWidth : helpers.getValueAtIndexOrDefault(dataset.pointBorderWidth, index, point._model.borderWidth); }, removeHoverStyle: function(point) { var dataset = this.chart.data.datasets[point._datasetIndex]; var index = point._index; point._model.radius = point.custom && point.custom.radius ? point.custom.radius : helpers.getValueAtIndexOrDefault(this.getDataset().radius, index, this.chart.options.elements.point.radius); point._model.backgroundColor = point.custom && point.custom.backgroundColor ? point.custom.backgroundColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBackgroundColor, index, this.chart.options.elements.point.backgroundColor); point._model.borderColor = point.custom && point.custom.borderColor ? point.custom.borderColor : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderColor, index, this.chart.options.elements.point.borderColor); point._model.borderWidth = point.custom && point.custom.borderWidth ? point.custom.borderWidth : helpers.getValueAtIndexOrDefault(this.getDataset().pointBorderWidth, index, this.chart.options.elements.point.borderWidth); } }); }).call(this);