diff --git a/samples/radar.html b/samples/radar.html index fd1214cbb..0605c76e7 100644 --- a/samples/radar.html +++ b/samples/radar.html @@ -14,6 +14,8 @@ + + diff --git a/src/controllers/controller.radar.js b/src/controllers/controller.radar.js index e7577887f..ce597d720 100644 --- a/src/controllers/controller.radar.js +++ b/src/controllers/controller.radar.js @@ -70,6 +70,26 @@ }); }, 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); @@ -123,34 +143,40 @@ // Update Points helpers.each(points, function(point, index) { - var pointPosition = scale.getPointPositionForValue(index, this.getDataset().data[index]); - - helpers.extend(point, { - // Utility - _datasetIndex: this.index, - _index: index, - - // Desired view properties - _model: { - x: reset ? scale.xCenter : pointPosition.x, // value not used in dataset scale, but we want a consistent API between scales - y: reset ? scale.yCenter : pointPosition.y, - - // Appearance - tension: point.custom && point.custom.tension ? point.custom.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), - skip: point.custom && point.custom.skip ? point.custom.skip : this.getDataset().data[index] === null, - - // Tooltip - hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius), - }, - }); + 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, + + // 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 : 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), + skip: point.custom && point.custom.skip ? point.custom.skip : this.getDataset().data[index] === null, + + // Tooltip + hitRadius: point.custom && point.custom.hitRadius ? point.custom.hitRadius : helpers.getValueAtIndexOrDefault(this.getDataset().hitRadius, index, this.chart.options.elements.point.hitRadius), + }, + }); + }, + updateBezierControlPoints: function() { helpers.each(this.getDataset().metaData, function(point, index) { var controlPoints = helpers.splineCurve( helpers.previousItem(this.getDataset().metaData, index, true)._model, @@ -164,7 +190,7 @@ // Prevent the bezier going outside of the bounds of the graph - // Cap puter bezier handles to the upper/lower scale bounds + // Cap outer bezier handles to the upper/lower scale bounds if (controlPoints.next.y > this.chart.chartArea.bottom) { point._model.controlPointNextY = this.chart.chartArea.bottom; } else if (controlPoints.next.y < this.chart.chartArea.top) { @@ -185,7 +211,6 @@ // Now pivot the point for animation point.pivot(); }, this); - }, draw: function(ease) { diff --git a/src/scales/scale.radialLinear.js b/src/scales/scale.radialLinear.js index 15169aa86..0a1a26b45 100644 --- a/src/scales/scale.radialLinear.js +++ b/src/scales/scale.radialLinear.js @@ -73,10 +73,12 @@ this.xCenter = this.chart.width / 2; this.yCenter = this.chart.height / 2; this.size = helpers.min([this.height, this.width]); - this.valuesCount = this.data.labels.length; this.labels = this.data.labels; this.drawingArea = (this.options.display) ? (this.size / 2) - (this.options.labels.fontSize / 2 + this.options.labels.backdropPaddingY) : (this.size / 2); }, + getValueCount: function() { + return this.data.labels.length; + }, update: function() { if (!this.options.lineArc) { this.setScaleSize(); @@ -201,7 +203,7 @@ }, this); }, getCircumference: function() { - return ((Math.PI * 2) / this.valuesCount); + return ((Math.PI * 2) / this.getValueCount()); }, setScaleSize: function() { /* @@ -252,13 +254,13 @@ radiusReductionLeft, maxWidthRadius; this.ctx.font = helpers.fontString(this.options.pointLabels.fontSize, this.options.pointLabels.fontStyle, this.options.pointLabels.fontFamily); - for (i = 0; i < this.valuesCount; i++) { + for (i = 0; i < this.getValueCount(); i++) { // 5px to space the text slightly out - similar to what we do in the draw function. pointPosition = this.getPointPosition(i, largestPossibleRadius); textWidth = this.ctx.measureText(helpers.template(this.options.labels.template, { value: this.labels[i] })).width + 5; - if (i === 0 || i === this.valuesCount / 2) { + if (i === 0 || i === this.getValueCount() / 2) { // If we're at index zero, or exactly the middle, we're at exactly the top/bottom // of the radar chart, so text will be aligned centrally, so we'll half it and compare // w/left and right text sizes @@ -271,13 +273,13 @@ furthestLeft = pointPosition.x - halfTextWidth; furthestLeftIndex = i; } - } else if (i < this.valuesCount / 2) { + } else if (i < this.getValueCount() / 2) { // Less than half the values means we'll left align the text if (pointPosition.x + textWidth > furthestRight) { furthestRight = pointPosition.x + textWidth; furthestRightIndex = i; } - } else if (i > this.valuesCount / 2) { + } else if (i > this.getValueCount() / 2) { // More than half the values means we'll right align the text if (pointPosition.x - textWidth < furthestLeft) { furthestLeft = pointPosition.x - textWidth; @@ -319,7 +321,7 @@ }, getIndexAngle: function(index) { - var angleMultiplier = (Math.PI * 2) / this.valuesCount; + var angleMultiplier = (Math.PI * 2) / this.getValueCount(); // Start from the top instead of right, so remove a quarter of the circle return index * angleMultiplier - (Math.PI / 2); @@ -362,7 +364,7 @@ } else { // Draw straight lines connecting each index ctx.beginPath(); - for (var i = 0; i < this.valuesCount; i++) { + for (var i = 0; i < this.getValueCount(); i++) { var pointPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.ticks[index])); if (i === 0) { ctx.moveTo(pointPosition.x, pointPosition.y); @@ -401,7 +403,7 @@ ctx.lineWidth = this.options.angleLines.lineWidth; ctx.strokeStyle = this.options.angleLines.color; - for (var i = this.valuesCount - 1; i >= 0; i--) { + for (var i = this.getValueCount() - 1; i >= 0; i--) { if (this.options.angleLines.show) { var outerPosition = this.getPointPosition(i, this.getDistanceFromCenterForValue(this.max)); ctx.beginPath();