Skip to content

Commit

Permalink
Polar area: startAngle in degrees, 0 at top. (#6936)
Browse files Browse the repository at this point in the history
* Polar area: startAngle in degrees, 0 at top.
Co-authored-by: Jukka Kurkela <[email protected]>
  • Loading branch information
benmccann authored and etimberg committed Jan 10, 2020
1 parent 53d13f7 commit d4109ca
Show file tree
Hide file tree
Showing 9 changed files with 59 additions and 22 deletions.
3 changes: 2 additions & 1 deletion docs/charts/polar.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand All @@ -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;
```
Expand Down
1 change: 1 addition & 0 deletions docs/getting-started/v3-migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
19 changes: 11 additions & 8 deletions src/controllers/controller.polarArea.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ defaults._set('polarArea', {
}
},

startAngle: -0.5 * Math.PI,
startAngle: 0,
legend: {
labels: {
generateLabels: function(chart) {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
},

/**
Expand Down Expand Up @@ -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;

Expand Down
8 changes: 4 additions & 4 deletions src/helpers/helpers.math.js
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

/**
Expand Down Expand Up @@ -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 {
Expand Down
11 changes: 4 additions & 7 deletions src/scales/scale.radialLinear.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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) {
Expand Down
35 changes: 35 additions & 0 deletions test/fixtures/controller.polarArea/angle-lines.json
Original file line number Diff line number Diff line change
@@ -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
}
}
}
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion test/specs/controller.polarArea.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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)',
Expand Down
2 changes: 1 addition & 1 deletion test/specs/scale.radialLinear.tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down

0 comments on commit d4109ca

Please sign in to comment.