feat: Add FlDotImagePainter for custom image dot markers - #2049
feat: Add FlDotImagePainter for custom image dot markers#2049InsoooooooooJANG wants to merge 3 commits into
Conversation
- Add FlDotImagePainter class that extends FlDotPainter - Support rendering custom images as dot markers on charts - Include static loadImageFromAsset() helper method - Add LineChartSample14 to demonstrate usage - Images must be pre-loaded asynchronously before use This allows users to display custom images (PNG, JPG, etc.) as dot markers instead of the default circle, square, or cross shapes.
| // Center the image at the offset | ||
| final drawOffset = offsetInCanvas - Offset(size / 2, size / 2); | ||
| final rect = Rect.fromLTWH(drawOffset.dx, drawOffset.dy, size, size); | ||
| paintImage( |
There was a problem hiding this comment.
Please use canvasWrapper.drawImage() instead of paintImage. This way, we keep the consistency and testability. Just like here:
fl_chart/lib/src/chart/base/axis_chart/axis_chart_painter.dart
Lines 296 to 305 in c83aa90
There was a problem hiding this comment.
paintImage is gone. I couldn't route it through CanvasWrapper though, and I'd rather check the direction with you than guess:
FlDotPainter.drawonly receives a rawCanvas—CanvasWrapper.drawDotunwraps it atcanvas_wrapper.dart:123, and that's the only call site.CanvasWrapperisn't exported fromlib/fl_chart.dart, so changingdrawto take one would makeFlDotPainterimpossible for users to implement without importingpackage:fl_chart/src/.... That's a public breaking change.Canvas.drawImage(the one in the code you linked) has no scaling — it draws at native size. Using it directly would silently ignoreFlDotImagePainter.size.- The raw-
Canvasshape also seems to be the convention for user-extensible painters:GaugeTickPainter,GaugeMarkerPainterandGaugePointerPainterall take aCanvasand callcanvas.drawLine/save/translatedirectly, as do the three built-in dot painters andFlSimpleErrorPainter.
So I dropped paintImage for canvas.drawImageRect with applyBoxFit(BoxFit.contain, ...), which keeps both size and the aspect ratio working. For the testability half of your point: draw is now unit-tested against MockCanvas and asserts the exact source/destination rects, the same way FlSimpleErrorPainter.draw is tested in axis_chart_data_test.dart.
If you'd rather have CanvasWrapper in the painter interfaces, I'm glad to do it — I just think it deserves its own breaking PR that exports canvas_wrapper.dart and converts all five painter interfaces at once, rather than changing only this one. Let me know which you prefer.
|
You also need to write some unit-tests in the end. |
# Conflicts: # example/lib/presentation/samples/chart_samples.dart
- Remove the loadImageFromAsset() helper from the library; loading an image is the user's responsibility now, so axis_chart_data.dart no longer imports flutter/services.dart - Replace paintImage() with canvas.drawImageRect() + applyBoxFit() so the draw call is verifiable in tests and `size` is still honored - Make mainColor a constructor field (it returned Colors.transparent, which made scatter tooltip text invisible via defaultScatterTooltipItem) - Add unit tests for equality, getSize, mainColor, lerp, hitTest and draw - Document FlDotImagePainter in the line chart docs - Strip the explanatory comments from LineChartSample14 and align it with the other line samples (AppColors, mounted guard, stable layout) - Load the image with ImmutableBuffer.fromUint8List + instantiateImageCodecWithSize; ImmutableBuffer.fromAsset throws UnsupportedError on web - Drop the unused ic_meal.png asset Related to imaNNeo#2050 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Thanks for the review, and sorry for the long silence on this one. All four points are addressed and Unit tests — added a One change beyond the review: I also dropped Verified with Heads-up on CI: |
Description
Adds
FlDotImagePainter, an implementation ofFlDotPainterthat draws adart:uiImageas the dot marker, instead of the built-in circle, square or cross shapes.The image is centered on the spot and scaled to fit inside a
sizexsizesquare, keeping its aspect ratio. SinceFlDotPainter.draw()is synchronous, the image has to be decoded before the painter is created — loading is left to the user (asset, network, generated), andLineChartSample14shows one way to do it.Checklist
///.example.Breaking Change?
Related Issues
Closes #2050