Skip to content

Commit 7a59f10

Browse files
committed
same spacing between pie slieces
1 parent a153556 commit 7a59f10

6 files changed

Lines changed: 96 additions & 4 deletions

File tree

src/controllers/controller.doughnut.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,8 @@ export default class DoughnutController extends DatasetController {
279279
endAngle: startAngle + circumference,
280280
circumference,
281281
outerRadius,
282-
innerRadius
282+
innerRadius,
283+
circular: false
283284
};
284285
if (includeOptions) {
285286
properties.options = sharedOptions || this.resolveDataElementOptions(i, arc.active ? 'active' : mode);

src/controllers/controller.polarArea.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,7 @@ export default class PolarAreaController extends DatasetController {
196196
outerRadius,
197197
startAngle,
198198
endAngle,
199+
circular: true,
199200
options: this.resolveDataElementOptions(i, arc.active ? 'active' : mode)
200201
};
201202

src/elements/element.arc.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,9 +135,13 @@ function pathArc(
135135
// the distance is the same as it would be without the spacing
136136
const noSpacingInnerRadius = innerR > 0 ? innerR - spacing : 0;
137137
const noSpacingOuterRadius = outerRadius > 0 ? outerRadius - spacing : 0;
138-
const avNogSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;
139-
const adjustedAngle = avNogSpacingRadius !== 0 ? (alpha * avNogSpacingRadius) / (avNogSpacingRadius + spacing) : alpha;
140-
spacingOffset = (alpha - adjustedAngle) / 2;
138+
const avgNoSpacingRadius = (noSpacingInnerRadius + noSpacingOuterRadius) / 2;
139+
if (circular && avgNoSpacingRadius > 0) {
140+
spacingOffset = Math.asin(Math.min(1, spacing / avgNoSpacingRadius));
141+
} else {
142+
const adjustedAngle = avgNoSpacingRadius !== 0 ? (alpha * avgNoSpacingRadius) / (avgNoSpacingRadius + spacing) : alpha;
143+
spacingOffset = (alpha - adjustedAngle) / 2;
144+
}
141145
}
142146

143147
const beta = Math.max(0.001, alpha * outerRadius - offset / PI) / outerRadius;
@@ -332,6 +336,7 @@ export default class ArcElement extends Element<ArcProps, ArcOptions> {
332336
outerRadius: number;
333337
pixelMargin: number;
334338
startAngle: number;
339+
circular: boolean;
335340

336341
constructor(cfg) {
337342
super();
@@ -344,6 +349,7 @@ export default class ArcElement extends Element<ArcProps, ArcOptions> {
344349
this.outerRadius = undefined;
345350
this.pixelMargin = 0;
346351
this.fullCircles = 0;
352+
this.circular = false;
347353

348354
if (cfg) {
349355
Object.assign(this, cfg);

test/specs/controller.doughnut.tests.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,22 @@ describe('Chart.controllers.doughnut', function() {
4646
expect(meta.data[3] instanceof Chart.elements.ArcElement).toBe(true);
4747
});
4848

49+
it('should mark arcs as non-circular', function() {
50+
var chart = window.acquireChart({
51+
type: 'doughnut',
52+
data: {
53+
datasets: [{
54+
data: [10, 20]
55+
}],
56+
labels: ['a', 'b']
57+
}
58+
});
59+
60+
var meta = chart.getDatasetMeta(0);
61+
expect(meta.data[0].circular).toBe(false);
62+
expect(meta.data[1].circular).toBe(false);
63+
});
64+
4965
it ('should reset and update elements', function() {
5066
var chart = window.acquireChart({
5167
type: 'doughnut',

test/specs/controller.polarArea.tests.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,22 @@ describe('Chart.controllers.polarArea', function() {
6666
expect(meta.data[3] instanceof Chart.elements.ArcElement).toBe(true);
6767
});
6868

69+
it('should mark arcs as circular', function() {
70+
var chart = window.acquireChart({
71+
type: 'polarArea',
72+
data: {
73+
datasets: [{
74+
data: [10, 20]
75+
}],
76+
labels: ['a', 'b']
77+
}
78+
});
79+
80+
var meta = chart.getDatasetMeta(0);
81+
expect(meta.data[0].circular).toBe(true);
82+
expect(meta.data[1].circular).toBe(true);
83+
});
84+
6985
it('should draw all elements', function() {
7086
var chart = window.acquireChart({
7187
type: 'polarArea',

test/specs/element.arc.tests.js

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,4 +303,56 @@ describe('Arc element tests', function() {
303303

304304
expect(arc.inRange(center.x, 1)).toBe(false);
305305
});
306+
307+
it('should use circular spacing only for circular arcs', function() {
308+
function createArc(circular) {
309+
return new Chart.elements.ArcElement({
310+
startAngle: 0,
311+
endAngle: Math.PI / 2,
312+
x: 0,
313+
y: 0,
314+
innerRadius: 0,
315+
outerRadius: 100,
316+
options: {
317+
circular: circular,
318+
spacing: 20,
319+
offset: 0,
320+
borderWidth: 0,
321+
borderRadius: 0,
322+
backgroundColor: 'red',
323+
borderColor: 'black'
324+
}
325+
});
326+
}
327+
328+
function firstOuterArcStartAngle(arc) {
329+
var ctx = window.createMockContext();
330+
arc.draw(ctx);
331+
332+
var arcCall = ctx.getCalls().filter(function(x) {
333+
return x.name === 'arc';
334+
})[0];
335+
if (arcCall) {
336+
return arcCall.args[3];
337+
}
338+
339+
var lineToCall = ctx.getCalls().filter(function(x) {
340+
return x.name === 'lineTo';
341+
})[0];
342+
var dx = lineToCall.args[0] - arc.x;
343+
var dy = lineToCall.args[1] - arc.y;
344+
return Math.atan2(dy, dx);
345+
}
346+
347+
var nonCircularStart = firstOuterArcStartAngle(createArc(false));
348+
var circularStart = firstOuterArcStartAngle(createArc(true));
349+
var alpha = Math.PI / 2;
350+
var spacing = 10; // draw() passes spacing / 2 to pathArc
351+
var avgNoSpacingRadius = 50;
352+
var adjustedAngle = (alpha * avgNoSpacingRadius) / (avgNoSpacingRadius + spacing);
353+
var linearSpacingOffset = (alpha - adjustedAngle) / 2;
354+
var circularSpacingOffset = Math.asin(Math.min(1, spacing / avgNoSpacingRadius));
355+
356+
expect(circularStart - nonCircularStart).toBeCloseTo(circularSpacingOffset - linearSpacingOffset, 6);
357+
});
306358
});

0 commit comments

Comments
 (0)