fix: keep single-slice pie/donut charts visible after the enter animation#98
Conversation
rudi-q#97) A pie/donut chart with a single slice (one category at 100%) rendered during the enter animation but vanished the instant it completed. At full progress the slice's sweep angle is exactly 2*pi. `Path.arcTo` draws nothing for a full-circle sweep (its start and stop unit vectors coincide), so the slice path collapses to an empty shape on the final frame. Mid-animation the sweep is still below 2*pi, which is why the slice only disappears once the animation finishes. Build the shape from ovals when the animated sweep reaches a full circle: a filled circle for a pie, and an even-odd outer/inner oval pair for a donut ring. Partial slices (sweep < 2*pi) keep the existing arcTo path, so multi-slice pies are unchanged.
|
@dmitriy-bty is attempting to deploy a commit to the DoublOne Team on Vercel. A member of the Team first needs to authorize it. |
WalkthroughThe pie slice path-generation logic in _drawPieAnimated was updated to correctly render slices when animatedSweepAngle reaches or exceeds 2π. It now constructs oval-based paths (addOval, with evenOdd fill for donut rings) instead of relying on arcTo, which previously produced empty paths for full-circle sweeps. ChangesFull-Circle Pie Slice Rendering Fix
Estimated code review effort: 2 (Simple) | ~10 minutes Related issues: Fixes reported bug where single-slice pie/donut charts disappear once the enter animation completes, since arcTo produces an empty path at a full 2π sweep. Suggested reviewers: rudi-q 🥧 A single slice, spinning ‘round, 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@lib/src/widgets/animated_chart_painter.dart`:
- Around line 2203-2223: The full-circle fix in animated_chart_painter.dart
needs regression coverage for the single-slice case. Add a widget test around
AnimatedCristalyseChartWidget that uses a one-point dataset and exercises both
PieGeometry(innerRadius: 0) and a donut inner radius, then pumpAndSettle and
verify the chart still renders/ remains visible. This should specifically cover
the path that now uses the full-circle oval logic instead of the arc path, so
the existing multi-category pie test is not sufficient.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: ASSERTIVE
Plan: Pro
Run ID: 7a08971f-593d-42d5-94d1-7d243c05ad63
📒 Files selected for processing (1)
lib/src/widgets/animated_chart_painter.dart
…cle fix Renders AnimatedChartPainter at animationProgress 1.0 for a one-category (100%) dataset and counts pixels that differ from the background, asserting the slice actually fills the disc (pie) and ring (donut). Fails against the pre-fix arcTo path (an empty full-circle sweep) and passes with the oval-based full-circle branch, covering the exact regression the existing multi-slice pie test cannot catch.
Summary
Fixes #97. A pie or donut chart with a single slice (one category making up
100% of the total) animates in correctly but disappears the moment the enter
animation finishes. It is only visible while the animation is still running.
Root cause
AnimatedChartPainter._drawPieAnimatedinlib/src/widgets/animated_chart_painter.dartbuilds each slice withPath.arcTo(outer/inner arcs for a donut at lines ~2238 and ~2249, the piewedge at line ~2261). The animated sweep angle is:
For a lone slice,
value / total == 1.0, sosweepAngle == 2*pi. At the finalframe
sliceProgress == 1.0, makinganimatedSweepAngleexactly2*pi.Path.arcTodraws nothing for a full2*pisweep: its start and stop unitvectors coincide, so the arc collapses to a zero-length segment and the slice
path ends up empty. This is unlike
Canvas.drawArc(used elsewhere in this filefor the radial gauges), which special-cases a full-circle sweep to a complete
oval. Mid-animation the sweep is still below
2*pi, which is exactly why theslice renders during the animation and only vanishes when it completes. The same
happens for a full pie (
innerRadius: 0), not just donuts.Change
In
_drawPieAnimated, whenanimatedSweepAnglereaches a full circle, build theshape from ovals instead of
arcTo:addOval).Partial slices (
sweep < 2*pi) keep the existingarcTopath untouched, somulti-slice pies and donuts render exactly as before. The change is contained to
the slice-path construction; the existing fill, stroke, label, and explode logic
apply to the new path unchanged (fill yields the disc/ring; stroke yields the
circle outline(s), which is the correct outline for a complete pie/ring).
Validation
code path that can produce a
2*piarcTosweep is a slice whosevalue / total == 1.0atsliceProgress == 1.0; for every partial sliceanimatedSweepAngle < 2*pi, so the branch and its output are unchanged.each slice's sweep is strictly less than
2*pi.test/single_slice_pie_test.dart): rendersAnimatedChartPainteratanimationProgress: 1.0for a one-category (100%)dataset and counts the pixels that differ from the background, asserting the
slice actually fills the disc (pie) and the ring (donut). The failure mode is
a visually empty fill — the painter still paints, just a zero-area path — so
the existing
findsOneWidget-style tests can't detect it; a pixel check can.Confirmed the test fails on the pre-fix
arcTopath (~800 non-backgroundpixels — the empty full-circle sweep) and passes with this change (~21k–32k
non-background pixels for the ring / disc), covering the exact regression the
existing multi-slice pie test misses.
flutter test— 299/299 passing, including the two newcases; no other test affected.
Reproduction
The donut renders during the animation, then vanishes when it completes on
main; with this change it stays as a full ring. SettinginnerRadius: 0reproduces the same behavior for a full pie.