]> git.ipfire.org Git - thirdparty/Chart.js.git/commitdiff
Polar area: startAngle in degrees, 0 at top. (#6936)
authorBen McCann <322311+benmccann@users.noreply.github.com>
Fri, 10 Jan 2020 23:30:29 +0000 (15:30 -0800)
committerEvert Timberg <evert.timberg+github@gmail.com>
Fri, 10 Jan 2020 23:30:29 +0000 (18:30 -0500)
* Polar area: startAngle in degrees, 0 at top.
Co-authored-by: Jukka Kurkela <jukka.kurkela@gmail.com>
docs/charts/polar.md
docs/getting-started/v3-migration.md
src/controllers/controller.polarArea.js
src/helpers/helpers.math.js
src/scales/scale.radialLinear.js
test/fixtures/controller.polarArea/angle-lines.json [new file with mode: 0644]
test/fixtures/controller.polarArea/angle-lines.png [new file with mode: 0644]
test/specs/controller.polarArea.tests.js
test/specs/scale.radialLinear.tests.js

index 3782d2b83a6ba973c1116265d3d2661ce7baf119..e4bb628597c47c0a3c75c69ad8f4626f03ee7eae 100644 (file)
@@ -101,7 +101,7 @@ These are the customisation options specific to Polar Area charts. These options
 
 | Name | Type | Default | Description
 | ---- | ---- | ------- | -----------
-| `startAngle` | `number` | `-0.5 * Math.PI` | Starting angle to draw arcs for the first item in a dataset.
+| `startAngle` | `number` | `0` | Starting angle to draw arcs for the first item in a dataset. In degrees, 0 is at top.
 | `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.
 
@@ -112,6 +112,7 @@ The polar area chart uses the [radialLinear](../axes/radial/linear.md) scale. Ad
 We can also change these defaults values for each PolarArea type that is created, this object is available at `Chart.defaults.polarArea`. Changing the global options only affects charts created after the change. Existing charts are not changed.
 
 For example, to configure all new polar area charts with `animateScale = false` you would do:
+
 ```javascript
 Chart.defaults.polarArea.animation.animateScale = false;
 ```
index 8ceb8fb01cf858aa70466fcd73383dafd5560cdf..5f8cea12636bffdc9ab3480f61cb9bea5eb0408b 100644 (file)
@@ -43,6 +43,7 @@ Chart.js 3.0 introduces a number of breaking changes. Chart.js 2.0 was released
 
 ### Options
 
+* `Polar area` `startAngle` option is now consistent with `Radar`, 0 is at top and value is in degrees. Default is changed from `-½π` to  `0`.
 * `scales.[x/y]Axes` arrays were removed. Scales are now configured directly to `options.scales` object with the object key being the scale Id.
 * `scales.[x/y]Axes.barPercentage` was moved to dataset option `barPercentage`
 * `scales.[x/y]Axes.barThickness` was moved to dataset option `barThickness`
index ac07a3bb300ad561c8f20aea002fe9398f6e2bf5..8eb1e6b0eccc35d2c8d530ad210d66a9ad037089 100644 (file)
@@ -32,7 +32,7 @@ defaults._set('polarArea', {
                }
        },
 
-       startAngle: -0.5 * Math.PI,
+       startAngle: 0,
        legend: {
                labels: {
                        generateLabels: function(chart) {
@@ -85,6 +85,12 @@ defaults._set('polarArea', {
        }
 });
 
+function getStartAngleRadians(deg) {
+       // radialLinear scale draws angleLines using startAngle. 0 is expected to be at top.
+       // Here we adjust to standard unit circle used in drawing, where 0 is at right.
+       return helpers.math.toRadians(deg) - 0.5 * Math.PI;
+}
+
 export default DatasetController.extend({
 
        dataElementType: elements.Arc,
@@ -117,13 +123,10 @@ export default DatasetController.extend({
        },
 
        update: function(mode) {
-               var me = this;
-               var meta = me._cachedMeta;
-               var arcs = meta.data;
-
-               me._updateRadius();
+               const arcs = this._cachedMeta.data;
 
-               me.updateElements(arcs, 0, mode);
+               this._updateRadius();
+               this.updateElements(arcs, 0, mode);
        },
 
        /**
@@ -154,7 +157,7 @@ export default DatasetController.extend({
                const scale = chart.scales.r;
                const centerX = scale.xCenter;
                const centerY = scale.yCenter;
-               const datasetStartAngle = opts.startAngle || 0;
+               const datasetStartAngle = getStartAngleRadians(opts.startAngle);
                let angle = datasetStartAngle;
                let i;
 
index 215b44db790f6b386601b896b46ec549509826b7..a08ed5ea5a5f1580138b484c5966356a12a80307 100644 (file)
@@ -83,11 +83,11 @@ export const sign = Math.sign ?
        };
 
 export function toRadians(degrees) {
-       return degrees * (Math.PI / 180);
+       return degrees * (PI / 180);
 }
 
 export function toDegrees(radians) {
-       return radians * (180 / Math.PI);
+       return radians * (180 / PI);
 }
 
 /**
@@ -118,8 +118,8 @@ export function getAngleFromPoint(centrePoint, anglePoint) {
 
        var angle = Math.atan2(distanceFromYCenter, distanceFromXCenter);
 
-       if (angle < (-0.5 * Math.PI)) {
-               angle += 2.0 * Math.PI; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
+       if (angle < (-0.5 * PI)) {
+               angle += TAU; // make sure the returned angle is in the range of (-PI/2, 3PI/2]
        }
 
        return {
index 433088b0f8e8ba2c9f8aa50bef0e927856af3679..0150ba70daacd63bc224ebc32f67ba012ab1f416 100644 (file)
@@ -2,7 +2,7 @@
 
 import defaults from '../core/core.defaults';
 import helpers from '../helpers/index';
-import {isNumber, toDegrees} from '../helpers/helpers.math';
+import {isNumber, toDegrees, toRadians, _normalizeAngle} from '../helpers/helpers.math';
 import LinearScaleBase from './scale.linearbase';
 import Ticks from '../core/core.ticks';
 
@@ -157,7 +157,7 @@ function fitWithPointLabels(scale) {
 
                // Add quarter circle to make degree 0 mean top of circle
                var angleRadians = scale.getIndexAngle(i);
-               var angle = toDegrees(angleRadians) % 360;
+               var angle = toDegrees(angleRadians);
                var hLimits = determineLimits(angle, pointPosition.x, textSize.w, 0, 180);
                var vLimits = determineLimits(angle, pointPosition.y, textSize.h, 90, 270);
 
@@ -380,14 +380,11 @@ class RadialLinearScale extends LinearScaleBase {
 
        getIndexAngle(index) {
                var chart = this.chart;
-               var angleMultiplier = 360 / chart.data.labels.length;
+               var angleMultiplier = Math.PI * 2 / chart.data.labels.length;
                var options = chart.options || {};
                var startAngle = options.startAngle || 0;
 
-               // Start from the top instead of right, so remove a quarter of the circle
-               var angle = (index * angleMultiplier + startAngle) % 360;
-
-               return (angle < 0 ? angle + 360 : angle) * Math.PI * 2 / 360;
+               return _normalizeAngle(index * angleMultiplier + toRadians(startAngle));
        }
 
        getDistanceFromCenterForValue(value) {
diff --git a/test/fixtures/controller.polarArea/angle-lines.json b/test/fixtures/controller.polarArea/angle-lines.json
new file mode 100644 (file)
index 0000000..01474c0
--- /dev/null
@@ -0,0 +1,35 @@
+{
+       "threshold": 0.05,
+    "config": {
+        "type": "polarArea",
+        "data": {
+            "labels": ["A", "B", "C", "D", "E"],
+            "datasets": [{
+                "data": [11, 16, 21, 7, 10],
+                "backgroundColor": [
+                    "rgba(255, 99, 132, 0.8)",
+                    "rgba(54, 162, 235, 0.8)",
+                    "rgba(255, 206, 86, 0.8)",
+                    "rgba(75, 192, 192, 0.8)",
+                    "rgba(153, 102, 255, 0.8)",
+                    "rgba(255, 159, 64, 0.8)"
+                ]
+            }]
+               },
+        "options": {
+            "responsive": false,
+            "legend": false,
+            "title": false,
+            "scale": {
+                               "display": true,
+                               "angleLines": {
+                                       "display": true,
+                                       "color": "#000"
+                               },
+                               "ticks": {
+                                       "display": false
+                               }
+            }
+        }
+    }
+}
diff --git a/test/fixtures/controller.polarArea/angle-lines.png b/test/fixtures/controller.polarArea/angle-lines.png
new file mode 100644 (file)
index 0000000..3890d7c
Binary files /dev/null and b/test/fixtures/controller.polarArea/angle-lines.png differ
index f7ea6e6a5bf9fe0f1742e5328219432736fb6a28..7780f9fde3bc0040fca5993f1c08eb6aa90e4c12 100644 (file)
@@ -156,7 +156,7 @@ describe('Chart.controllers.polarArea', function() {
                                showLines: true,
                                legend: false,
                                title: false,
-                               startAngle: 0, // default is -0.5 * Math.PI
+                               startAngle: 90, // default is 0
                                elements: {
                                        arc: {
                                                backgroundColor: 'rgb(255, 0, 0)',
index a64157a7e69e6bd868902327ef3c96903040921d..d8a50712f76d8ee17b998b0f8a3f4885e23e5078 100644 (file)
@@ -535,7 +535,7 @@ describe('Test the radial linear scale', function() {
                        scale.ctx.getCalls().filter(function(x) {
                                return x.name === 'setTextAlign';
                        }).forEach(function(x, i) {
-                               expect(x.args[0]).toBe(expected.textAlign[i]);
+                               expect(x.args[0]).withContext('startAngle: ' + expected.startAngle + ', tick: ' + i).toBe(expected.textAlign[i]);
                        });
 
                        scale.ctx.getCalls().filter(function(x) {