fix: prevent stroke gap on single-slice pie/donut charts (Closes #5084) - #5267
fix: prevent stroke gap on single-slice pie/donut charts (Closes #5084)#5267waterWang wants to merge 4 commits into
Conversation
…charts#5084) When a pie or donut chart has only one data point, the slice occupies the full 360 degrees. The stroke at the start/end junction creates a visible gap from the center to the edge of the circle. Fix: set strokeWidth to 0 when there is only one slice, so no stroke is applied to the single full-circle path.
|
Thanks for digging into #5084. The diagnosis is right, but I'd like some changes before this can land: the fix is both incomplete and over-broad, and the PR carries an unrelated axis-scale regression. I checked all of the points below by running the PR branch locally. 1. Blocker: unrelated breaking change in
|
| branch | result |
|---|---|
main |
[0, 1.17, 2.34, 3.51, 4.68, 5.85, 7.02] |
| this PR | [0, 5, 10, 15, 20, 25, 30] |
The user-set max: 7 is discarded and the axis runs to 30. No unit test covers it (the unit suite is green on both branches), so this would ship unnoticed. Please drop this hunk from the PR.
2. The fix misses the actual reported case
sectorAngleArr.length === 1 keys off the series count, not the slice angle. A slice reaches 360 degrees whenever its siblings are zero. On this branch, series: [44, 0, 0] with stroke: { show: true, width: 4 } renders:
[{"stroke-width":"4","angle":"360"},{"stroke-width":"4","angle":"0"},{"stroke-width":"4","angle":"0"}]Full-circle slice, stroke still 4, so the seam from #5084 is still visible. That is a common data shape (filtered data, or a single non-zero category).
3. The fix regresses a case that was never broken
The same condition fires for single-series semicircle pies, which are not full circles and legitimately want an outline. With plotOptions.pie: { startAngle: -90, endAngle: 90 } and series: [44]:
[{"stroke-width":"0","angle":"180"}]The half-disc silently loses its configured 4px border. Single-slice donuts ([{"stroke-width":"0","angle":"360"}]) also lose the inner hollow border, which is a deliberate design element for a lot of users rather than an artifact.
Related: Pie.js:61 still subtracts stroke.width from w.globals.radialSize, so a single-slice pie now draws smaller than it should for a stroke that no longer exists.
4. Suggested direction: fix the geometry, not the stroke
The root cause is in getPiePath. The "prevent overlap" clamp pulls endDeg back by 0.01 degrees:
if (Math.ceil(endDeg) >= this.fullAngle + (...)) {
endDeg = this.fullAngle + (...) - 0.01
}and the pie branch then appends L centerX centerY L x1 y1. For a 360 degree span those two nearly coincident radial lines to the center are exactly what the stroke paints as a line from center to edge.
The targeted fix is a special case in getPiePath when the span covers the whole angle (spanDeg >= fullAngle && fullAngle >= 360):
- pie / polarArea: emit a closed circle (two 180 degree arcs plus
z), with no radial lines to the center - donut: emit the outer circle plus a reverse-sweep inner circle as one closed path (an annulus)
That keeps the configured stroke rendering correctly as a clean ring outline, fixes the [44, 0, 0] and legend-collapsed cases for free, and leaves semicircles untouched.
5. Tests
tests/unit/pie-stroke-repro.spec.jslooks like a leftover scratch repro. It duplicates the two tests already added topie-chart.spec.js, importsbeforeEachwithout using it, and has no trailing newline. Please delete it.- In
pie-chart.spec.js, the newdescribe('stroke')block is inserted after the})that closesdescribe('Pie chart'), so it ends up as a top-level block with 2-space indentation, wedged between the pie section and theDONUT CHART TESTSbanner comment. It runs, but it is in the wrong place and mis-indented. - Missing coverage for the cases that break it:
[44, 0, 0], a single-slice semicircle, and a single-slice donut.
To move forward
- Drop the
Scales.jshunk. - Rework the fix in
getPiePathto emit a true circle / annulus for full-angle slices instead of zeroing the stroke. - Delete the duplicate spec file and re-nest the new tests inside
describe('Pie chart'). - Add cases for zero-valued siblings, semicircles, and donuts.
Happy to review again once those are in.
Description
Fixes #5084 — when a pie or donut chart has only one data point, the slice occupies the full 360 degrees. With
strokeenabled, the stroke at the start/end junction creates a visible gap from the center to the edge of the circle.Fix
In
src/charts/Pie.js, setstrokeWidthto0when there is only one slice (sectorAngleArr.length === 1), so no stroke is applied to the single full-circle path. Multi-slice charts are unaffected and keep their configured stroke.Tests
Added regression coverage in
tests/unit/pie-chart.spec.js:stroke-width: 0stroke-widthAll 39 tests in
pie-chart.spec.jspass.Acceptance Criteria