How to change the icon size of Google Maps marker in Flutter?

前端 未结 14 789
不知归路
不知归路 2020-12-07 12:32

I am using google_maps_flutter in my flutter app to use google map I have custom marker icon and I load this with BitmapDescriptor.fromAsset(\"images/car.

14条回答
  •  没有蜡笔的小新
    2020-12-07 13:22

    TL;DR: As long as are able to encode any image into raw bytes such as Uint8List, you should be fine using it as a marker.


    As of now, you can use Uint8List data to create your markers with Google Maps. That means that you can use raw data to paint whatever you want as a map marker, as long as you keep the right encode format (which in this particular scenario, is a png).

    I will go through two examples where you can either:

    1. Pick a local asset and dynamically change its size to whatever you want and render it on the map (a Flutter logo image);
    2. Draw some stuff in canvas and render it as marker as well, but this can be any render widget.

    Besides this, you can even transform a render widget in an static image and thus, use it as marker too.


    1. Using an asset

    First, create a method that handles the asset path and receives a size (this can be either the width, height, or both, but using only one will preserve ratio).

    import 'dart:ui' as ui;
    
    Future getBytesFromAsset(String path, int width) async {
      ByteData data = await rootBundle.load(path);
      ui.Codec codec = await ui.instantiateImageCodec(data.buffer.asUint8List(), targetWidth: width);
      ui.FrameInfo fi = await codec.getNextFrame();
      return (await fi.image.toByteData(format: ui.ImageByteFormat.png)).buffer.asUint8List();
    }
    

    Then, just add it to your map using the right descriptor:

    final Uint8List markerIcon = await getBytesFromAsset('assets/images/flutter.png', 100);
    final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));
    

    This will produce the following for 50, 100 and 200 width respectively.


    2. Using canvas

    You can draw anything you want with canvas and then use it as a marker. The following will produce some simple rounded box with a Hello world! text in it.

    So, first just draw some stuff using the canvas:

    Future getBytesFromCanvas(int width, int height) async {
      final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
      final Canvas canvas = Canvas(pictureRecorder);
      final Paint paint = Paint()..color = Colors.blue;
      final Radius radius = Radius.circular(20.0);
      canvas.drawRRect(
          RRect.fromRectAndCorners(
            Rect.fromLTWH(0.0, 0.0, width.toDouble(), height.toDouble()),
            topLeft: radius,
            topRight: radius,
            bottomLeft: radius,
            bottomRight: radius,
          ),
          paint);
      TextPainter painter = TextPainter(textDirection: TextDirection.ltr);
      painter.text = TextSpan(
        text: 'Hello world',
        style: TextStyle(fontSize: 25.0, color: Colors.white),
      );
      painter.layout();
      painter.paint(canvas, Offset((width * 0.5) - painter.width * 0.5, (height * 0.5) - painter.height * 0.5));
      final img = await pictureRecorder.endRecording().toImage(width, height);
      final data = await img.toByteData(format: ui.ImageByteFormat.png);
      return data.buffer.asUint8List();
    }
    

    and then use it the same way, but this time providing any data you want (eg. width and height) instead of the asset path.

    final Uint8List markerIcon = await getBytesFromCanvas(200, 100);
    final Marker marker = Marker(icon: BitmapDescriptor.fromBytes(markerIcon));
    

    and here you have it.

提交回复
热议问题