Skip to content

feat: Add FlDotImagePainter for custom image dot markers - #2049

Open
InsoooooooooJANG wants to merge 3 commits into
imaNNeo:mainfrom
InsoooooooooJANG:feature/fldot-image
Open

feat: Add FlDotImagePainter for custom image dot markers#2049
InsoooooooooJANG wants to merge 3 commits into
imaNNeo:mainfrom
InsoooooooooJANG:feature/fldot-image

Conversation

@InsoooooooooJANG

@InsoooooooooJANG InsoooooooooJANG commented Jan 25, 2026

Copy link
Copy Markdown

Description

Adds FlDotImagePainter, an implementation of FlDotPainter that draws a dart:ui Image as 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 size x size square, keeping its aspect ratio. Since FlDotPainter.draw() is synchronous, the image has to be decoded before the painter is created — loading is left to the user (asset, network, generated), and LineChartSample14 shows one way to do it.

final data = await rootBundle.load('assets/dot.png');
final buffer = await ui.ImmutableBuffer.fromUint8List(data.buffer.asUint8List());
final codec = await PaintingBinding.instance.instantiateImageCodecWithSize(buffer);
final frame = await codec.getNextFrame();

final painter = FlDotImagePainter(image: frame.image, size: 20);

LineChartBarData(
  spots: spots,
  dotData: FlDotData(
    getDotPainter: (spot, percent, barData, index) => painter,
  ),
)
image

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation and added dartdoc comments with ///.
  • I have updated/added relevant examples in example.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

Closes #2050

- 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.
@InsoooooooooJANG InsoooooooooJANG changed the title feat: add FlDotImagePainter for custom image dot markers Draft: add FlDotImagePainter for custom image dot markers Jan 25, 2026
Comment thread lib/src/chart/base/axis_chart/axis_chart_data.dart Outdated
// 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(

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use canvasWrapper.drawImage() instead of paintImage. This way, we keep the consistency and testability. Just like here:

if (line.image != null) {
final centerX = line.image!.width / 2;
final centerY = line.image!.height / 2;
final centeredImageOffset = Offset(centerX, to.dy - centerY);
canvasWrapper.drawImage(
line.image!,
centeredImageOffset,
_imagePaint,
);
}

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

paintImage is gone. I couldn't route it through CanvasWrapper though, and I'd rather check the direction with you than guess:

  • FlDotPainter.draw only receives a raw CanvasCanvasWrapper.drawDot unwraps it at canvas_wrapper.dart:123, and that's the only call site.
  • CanvasWrapper isn't exported from lib/fl_chart.dart, so changing draw to take one would make FlDotPainter impossible for users to implement without importing package: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 ignore FlDotImagePainter.size.
  • The raw-Canvas shape also seems to be the convention for user-extensible painters: GaugeTickPainter, GaugeMarkerPainter and GaugePointerPainter all take a Canvas and call canvas.drawLine/save/translate directly, as do the three built-in dot painters and FlSimpleErrorPainter.

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.

Comment thread example/lib/presentation/samples/line/line_chart_sample14.dart Outdated
@imaNNeo

imaNNeo commented Apr 10, 2026

Copy link
Copy Markdown
Owner

You also need to write some unit-tests in the end.

insoo-jang and others added 2 commits August 11, 2026 01:39
# 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>
@InsoooooooooJANG InsoooooooooJANG changed the title Draft: add FlDotImagePainter for custom image dot markers feat: Add FlDotImagePainter for custom image dot markers Aug 11, 2026
@InsoooooooooJANG

Copy link
Copy Markdown
Author

Thanks for the review, and sorry for the long silence on this one. All four points are addressed and main is merged in, so the conflict is gone.

Unit tests — added a FlDotImagePainter group to test/chart/base/axis_chart/axis_chart_data_test.dart covering equality, getSize, mainColor, same-type and cross-type lerp, the inherited hitTest, and draw (asserting the exact src/dst rects that come out of applyBoxFit, plus that a square image fills the whole dot). MockCanvas was already generated for that file, so no make codeGen needed.

One change beyond the review: mainColor was returning Colors.transparent, which would render scatter-chart tooltip text invisible (it feeds the text color at scatter_chart_data.dart:577). It's now a constructor field defaulting to Colors.green, matching FlDotCirclePainter.color.

I also dropped example/assets/icons/ic_meal.png — the sample loads the existing image_annotation.png, so that file was never referenced.

Verified with make runTests (673 passing) and make checkFormat, and I ran the example on web to confirm the sample actually renders.

Heads-up on CI: make analyze is currently failing on main itself — the run for f3a5758 is red with 167 pre-existing EquatableMixin is deprecated infos coming from a newer equatable resolving on current stable. So the red check here isn't from these changes. Want me to send a separate PR that switches those over to Equatable?

@InsoooooooooJANG
InsoooooooooJANG marked this pull request as ready for review August 11, 2026 01:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature Request] Add FlDotImagePainter to support custom image dot markers

3 participants