diff --git a/docs/charts/polar.md b/docs/charts/polar.md index 8403a387230..e11dfadeb0d 100644 --- a/docs/charts/polar.md +++ b/docs/charts/polar.md @@ -96,6 +96,7 @@ These are the customisation options specific to Polar Area charts. These options | `startAngle` | `number` | `-0.5 * Math.PI` | Starting angle to draw arcs for the first item in a dataset. | `animation.animateRotate` | `boolean` | `true` | If true, the chart will animate in with a rotation animation. This property is in the `options.animation` object. | `animation.animateScale` | `boolean` | `true` | If true, will animate scaling the chart from the center outwards. +| `angles` | `array` | `(2*Math.PI)/serieCount` | Computed angles to draw each item arc. ## Default Options diff --git a/src/controllers/controller.polarArea.js b/src/controllers/controller.polarArea.js index 1e0e30ba2dd..0a48ff66b91 100644 --- a/src/controllers/controller.polarArea.js +++ b/src/controllers/controller.polarArea.js @@ -131,15 +131,17 @@ module.exports = DatasetController.extend({ var starts = me._starts = []; var angles = me._angles = []; var arcs = meta.data; - var i, ilen, angle; + var i, ilen, angle, convertedAngles; + var optionsAngles = me.chart.options.angles || []; me._updateRadius(); meta.count = me.countVisibleElements(); + convertedAngles = me._convertAngles(optionsAngles); for (i = 0, ilen = dataset.data.length; i < ilen; i++) { starts[i] = start; - angle = me._computeAngle(i); + angle = me._computeAngle(i, convertedAngles[i]); angles[i] = angle; start += angle; } @@ -251,15 +253,9 @@ module.exports = DatasetController.extend({ /** * @private */ - _computeAngle: function(index) { + _computeAngle: function(index, angle) { var me = this; - var count = this.getMeta().count; var dataset = me.getDataset(); - var meta = me.getMeta(); - - if (isNaN(dataset.data[index]) || meta.data[index].hidden) { - return 0; - } // Scriptable options var context = { @@ -271,7 +267,46 @@ module.exports = DatasetController.extend({ return resolve([ me.chart.options.elements.arc.angle, - (2 * Math.PI) / count + angle ], context, index); + }, + + /** + * if no angles options, circumference = 2*PI and each arc will be (2*PI)/arcCount + * if angles options, circumference = sum(angles) + * if angles.length < arcCount => undefined angles will be set to (2*PI)/arcCount, + * defined angles will be recompute to fill circumference-sum(undefinedAngles) stay proportional to original values + * if angles.length > arcCount => circumference remains the same and existing angles will be recompute to stay proportional to original values + * @private + */ + _convertAngles: function(angles) { + var me = this; + var dataset = me.getDataset(); + var meta = me.getMeta(); + var angle, ratio; + var initialCircumference = 0; + var convertedAngles = []; + var circumference = angles.length ? angles.reduce(function(a, b) { + return a + b; + }) : Math.PI * 2; + var defaultAngle = circumference / dataset.data.length; + + meta.data.forEach(function(element, index) { + if (isNaN(dataset.data[index]) || element.hidden) { + angle = 0; + } else if (index >= angles.length) { + angle = defaultAngle; + } else { + angle = angles[index]; + } + initialCircumference += angle; + convertedAngles.push(angle); + }); + ratio = circumference / initialCircumference; + + return convertedAngles.map(function(item) { + return item * ratio; + }); } + });