svgdartflutter

Using SVG markers in google_maps_flutter Flutter plugin


Is it possible to use SVG paths to create a marker with the google_maps_flutter plugin? I know you can use .png files by using:

icon: BitmapDescriptor.fromAsset("images/myFile.png")

How about SVG paths?

Thanks


Solution

  • This can be achieved using the flutter_svg package.

    import 'dart:ui' as ui; // imported as ui to prevent conflict between ui.Image and the Image widget
    import 'package:flutter/services.dart';
    import 'package:flutter_svg/flutter_svg.dart';
    import 'package:google_maps_flutter/google_maps_flutter.dart';
    
    Future<BitmapDescriptor> _bitmapDescriptorFromSvgAsset(BuildContext context, String assetName) async {
        // Read SVG file as String
        String svgString = await DefaultAssetBundle.of(context).loadString(assetName);
        // Create DrawableRoot from SVG String
        DrawableRoot svgDrawableRoot = await svg.fromSvgString(svgString, null);
    
        // toPicture() and toImage() don't seem to be pixel ratio aware, so we calculate the actual sizes here
        MediaQueryData queryData = MediaQuery.of(context);
        double devicePixelRatio = queryData.devicePixelRatio;
        double width = 32 * devicePixelRatio; // where 32 is your SVG's original width
        double height = 32 * devicePixelRatio; // same thing
    
        // Convert to ui.Picture
        ui.Picture picture = svgDrawableRoot.toPicture(size: Size(width, height));
    
        // Convert to ui.Image. toImage() takes width and height as parameters
        // you need to find the best size to suit your needs and take into account the
        // screen DPI
        ui.Image image = await picture.toImage(width, height);
        ByteData bytes = await image.toByteData(format: ui.ImageByteFormat.png);
        return BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
    }
    

    You can then use the BitmapDescriptor to create a Marker as usual:

    BitmapDescriptor bitmapDescriptor = await _bitmapDescriptorFromSvgAsset(context, 'assets/images/someimage.svg');
    Marker marker = Marker(markerId: MarkerId('someId'), icon: bitmapDescriptor, position: LatLng(someLatitude, someLongitude));