如何在google_maps_flutter Flutter插件中使用SVG标记?

时间:2019-06-05 09:41:56

标签: svg flutter google-maps-markers

我希望使用.svg图像作为图标放置标记。我正在使用google_maps_flutter库。这适用于.png转换后的图像,但我找不到直接使用.svg文件的方法。

阅读此问题后,我将在此发布:Using SVG markers in google_maps_flutter Flutter plugin

并尝试使用此线程中所述的fromAssetImage方法:How to change the icon size of Google Map marker in Flutter?

我希望这个新版本的库能够帮助解决我的问题。

我尝试使用以下代码解决它:

MapWidget类

for (Place place in widget.places) {
          place.toMarker(
            context,
            () => _onPlaceTapped(place),
          ).then(setState((){
            markerSet.add
          }));
      }

地方课程

Future<Marker> toMarker(BuildContext context, VoidCallback onTap) async {
    return Marker(
      markerId: MarkerId(id.toString()),
      position: LatLng(lat, lon),
      icon: await category.markerIcon(createLocalImageConfiguration(context)),
      onTap: onTap,
    );

类别

Future<BitmapDescriptor> markerIcon(ImageConfiguration configuration) async {
    BitmapDescriptor b;
    switch (type) {
      case CategoryType.FirstCategory:
        b = await BitmapDescriptor.fromAssetImage(configuration, 'assets/markers/marker-first.svg');
        break;
      case CategoryType.SecondCategory:
        b = await BitmapDescriptor.fromAssetImage(configuration, 'assets/markers/marker-second.svg');
        break;
      default:
        b = await BitmapDescriptor.fromAssetImage(configuration, 'assets/markers/marker-third.svg');
        break;
    }

    return b;
  }

如果您想知道图像的路径已经添加到pubspec.yaml。

我希望默认的红色Google标记会被地图上的一些自定义标记(每个自定义标记上应该有一个小图标图像)代替,但是只显示默认标记(而不是switch语句中的默认标记,我说到Google的默认标记)。

使用iOS模拟器和google_maps_flutter 0.5.15 + 1库版本没有错误消息。

2 个答案:

答案 0 :(得分:0)

您可以在这里找到该问题的答案:

Using SVG markers in google_maps_flutter Flutter plugin

我尝试了rednuht的答案,它的工作原理很吸引人。

编辑(摘要)

答案需要使用flutter_svg插件(^ 0.13或0.14.1似乎对我自己有用)。

首先,创建一个函数,该函数将为您提供资产中的BitmapDescriptor。确保资产已在您的pubspec文件中声明。

import 'dart:ui' as ui;
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';


Future<BitmapDescriptor> _bitmapDescriptorFromSvgAsset(BuildContext context, String assetName) async {
    String svgString = await DefaultAssetBundle.of(context).loadString(assetName);
    DrawableRoot drawableRoot = await svg.fromSvgString(svgString, null);
    ui.Picture picture = svgDrawableRoot.toPicture();
    ui.Image image = await picture.toImage(26, 37);
    ByteData bytes = await image.toByteData(format: ui.ImageByteFormat.png);
    return BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
}

我在应用程序的开头实例化了一个Map对象,这样我就可以使用BitmapDescriptors而不用使用很多异步/等待调用。

data_model.dart

Map<CategoryType, BitmapDescriptor> descriptors = Map<Category, BitmapDescriptor>();

Future<void> loadBitmapDescriptors(context) async {
    descriptors[CategoryType.FirstCatgory] = await _bitmapDescriptorFromSvgAsset(context, 'assets/markers/marker-first.svg');
    descriptors[CategoryType.SecondCategory] = await _bitmapDescriptorFromSvgAsset(context, 'assets/markers/marker-second.svg');
    descriptors[CategoryType.ThirdCategory] = await _bitmapDescriptorFromSvgAsset(context, 'assets/markers/marker-third.svg');
  }

main.dart

DataModel.of(context).loadBitmapDescriptors(context);

所以在那之后我要做的就是在需要时正确调用它。

Marker marker = Marker(markerId: MarkerId(id.toString()), icon: descriptors[category], position: LatLng(lat, lon));

答案 1 :(得分:0)

我也遇到了同样的问题,由于没有de devicePixelRatio而导致了这种实现,结果显示像素化标记。

Future<BitmapDescriptor> getBitmapDescriptorFromSVGAsset(
    BuildContext context,
    String svgAssetLink, {
    Size size = const Size(30, 30),
  }) async {
    String svgString = await DefaultAssetBundle.of(context).loadString(
      svgAssetLink,
    );
    final drawableRoot = await svg.fromSvgString(
      svgString,
      'debug: $svgAssetLink',
    );
    final ratio = ui.window.devicePixelRatio.ceil();
    final width = size.width.ceil() * ratio;
    final height = size.height.ceil() * ratio;
    final picture = drawableRoot.toPicture(
      size: Size(
        width.toDouble(),
        height.toDouble(),
      ),
    );
    final image = await picture.toImage(width, height);
    final byteData = await image.toByteData(format: ui.ImageByteFormat.png);
    final uInt8List = byteData.buffer.asUint8List();
    return BitmapDescriptor.fromBytes(uInt8List);
  }