Как использовать маркеры SVG в плагине google_maps_flutter Flutter?

Я хочу разместить маркеры, используя изображения .svg в качестве значков. Я использую библиотеку google_maps_flutter. Это работало с изображениями, преобразованными в .png, но я не нашел способа напрямую использовать файлы .svg.

Я размещаю здесь после прочтения этой проблемы: Использование маркеров SVG в google_maps_flutter Плагин Flutter

И пытаясь использовать метод fromAssetImage, как описано в этом потоке: Как изменить размер значка маркера Google Map во 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 сообщение об ошибке отсутствует.


person wenolOaR    schedule 05.06.2019    source источник
comment
BitmapDescriptor.fromAssetImage () не работает с файлами SVG. Пожалуйста, проверьте мой ответ на вопрос, который вы связали: stackoverflow.com/a/57609840/2344535   -  person rednuht    schedule 22.08.2019
comment
Возможный дубликат Использование маркеров SVG в подключаемом модуле google_maps_flutter Flutter   -  person rednuht    schedule 22.08.2019
comment
Действительно, мы говорим об одном и том же. Я попробовал то, что было рекомендовано в этом посте, но у меня это не сработало. Итак, я подумал, что могу создать сообщение, показывающее код, который я пробовал. Должен ли я закрыть вопрос в таком случае? Я вижу, что есть новые ответы, так что теперь я могу найти там свое решение.   -  person wenolOaR    schedule 23.08.2019
comment
Вы пробовали использовать flutter_svg? Я считаю, что ответ с использованием этого пакета еще не был опубликован в то время, когда вы создавали свой вопрос.   -  person rednuht    schedule 23.08.2019
comment
Да не было. Я имел в виду свою ситуацию тогда. Я попробую ваше решение, как только смогу.   -  person wenolOaR    schedule 26.08.2019
comment
Большое спасибо @rednuht! Это сработало как шарм. Поскольку я пока не могу прокомментировать ваш ответ (‹50 респондентов), я скажу вам здесь переименовать drawableRoot в svgDrawableRoot и, возможно, добавить комментарий о том, что размеры, используемые в picture.toPicture(32, 32), должны быть тщательно выбраны, иначе изображение svg выиграет не отображаются полностью.   -  person wenolOaR    schedule 05.09.2019
comment
У вас есть идея, как масштабировать получившееся изображение вверх и вниз? Мои маркеры слишком маленькие, когда я использую изображение svg.   -  person wenolOaR    schedule 05.09.2019
comment
Я также обнаружил, что масштабирование сложно. DrawableRoot.toPicture () принимает аргумент размера, который вы можете установить в дополнение к параметрам размера в picture.toImage (). Ни один из них, похоже, не принимает во внимание соотношение пикселей устройства. Итак, вам нужно получить соотношение пикселей из MediaQuery и умножить его на желаемый размер. Я обновил ответ, чтобы отразить это.   -  person rednuht    schedule 05.09.2019


Ответы (2)


Вы можете найти ответ на этот вопрос здесь:

Использование маркеров SVG в подключаемом модуле google_maps_flutter Flutter

Я попробовал ответить 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);
    //Draws string representation of svg to DrawableRoot
    DrawableRoot svgDrawableRoot = 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 без использования большого количества вызовов async / await.

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));
person wenolOaR    schedule 05.09.2019
comment
Кратко опишите содержание, так как ссылка может быть устаревшей - person Circle Hsiao; 05.09.2019

У меня была такая же проблема, и я закончил эту реализацию из-за отсутствия устройстваPixelRatio. Он показывал пиксельные маркеры.

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);
  }
person Santiago M    schedule 28.08.2020