-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Description
Hi there,
I'm building a map application in which I have A LOT of different marker designs to display (depending on the kind of POI).
As I have to constantly renderer different marker on the map, I decided to optimize performance by loading all the marker design from assets file (using BitmapDescriptor.fromImageAsset() function) at the beginning and storing that in a
Map<int, BitmapDescriptor>It worked great, the performance was good.
I then decided to generate my markers with code instead of loading them from image assets using the following code:
Future<BitmapDescriptor> generatePostClusterMarker(
String text, double sizeFactor, double pixelRatio) async {
print(pixelRatio);
Function wRatio = (input) => input * pixelRatio;
final stopwatch = Stopwatch()..start();
final ui.PictureRecorder recorder = ui.PictureRecorder();
final Canvas canvas = Canvas(recorder);
final TextSpan textSpan = TextSpan(
style: TextStyle(
color: Colors.pink,
fontSize: wRatio(13 * sizeFactor),
fontWeight: FontWeight.w900),
text: text,
);
final TextPainter textPainter = TextPainter(
text: textSpan,
textDirection: TextDirection.ltr,
textAlign: TextAlign.center);
textPainter.layout();
double diameter = 100 * sizeFactor;
double blurSigma = wRatio(5);
Size boxSize = Size(diameter, diameter);
Size outputSize =
Size(boxSize.width + 2 * blurSigma, boxSize.height + 2 * blurSigma);
// paint shadow
canvas.drawCircle(
Offset(outputSize.width / 2, outputSize.height / 2),
diameter / 2,
Paint()
..color = Colors.black.withAlpha(50)
..maskFilter = MaskFilter.blur(BlurStyle.normal, blurSigma / 2));
// paint rounded box
canvas.drawCircle(
Offset(outputSize.width / 2, outputSize.height / 2),
diameter / 2,
Paint()
..color = Colors.white
..isAntiAlias = true
..style = PaintingStyle.fill
..filterQuality = FilterQuality.high);
// paint text
textPainter.paint(
canvas,
Offset((outputSize.width / 2) - (textPainter.size.width / 2),
(outputSize.height / 2) - (textPainter.size.height / 2)));
final ui.Picture picture = recorder.endRecording();
final ByteData pngBytes = await picture
.toImage(outputSize.width.toInt(), outputSize.height.toInt())
.then((image) => image.toByteData(format: ui.ImageByteFormat.png));
print(
'Marker $text [${outputSize.width}x${outputSize.height}] generated in ${stopwatch.elapsed.inMilliseconds}');
picture.dispose();
return BitmapDescriptor.fromBytes(pngBytes.buffer.asUint8List());
}again loading them all at the beginning and storing all the resulting BitmapDescriptor in a Map.
But after doing that, the performance took a big hit, markers now take longer to render on the map and the whole thing is not fluid as it used to be when they were loaded from image assets.
What I don't understand is that after the initial loading, the generated Map<int, BitmapDescriptor> should contain exactly the same thing (as the generated markers are exported with the same image size as the image assets), so why is performance worst?
What really is the difference between this:

and this:
Am I missing something here? What else can I do to improve marker loading performance?
Cheers!
Theo
