在google_maps_flutter Flutter插件中使用SVG标记

ahy6op9u  于 2023-02-25  发布在  Flutter
关注(0)|答案(4)|浏览(192)

是否可以使用SVG路径来创建带有google_maps_flutter插件的标记?我知道您可以通过以下方式使用.png文件:

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

SVG路径如何?
谢谢

oyxsuwqo

oyxsuwqo1#

这可以通过使用flutter_svg封装来实现。

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());
}

然后,您可以像往常一样使用BitmapDescriptor创建标记:

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

5lhxktic2#

以下是一些选项:

  • getBitmapDescriptorFromSvgAsset-来自资产的SVG
  • getBitmapDescriptorFromSvgString- svg作为来自db/remote/whatever的字符串
class BitmapDescriptorHelper{
  static Future<BitmapDescriptor> getBitmapDescriptorFromSvgAsset(
      BuildContext context, String svgAssetLink) async {
    final svgImage = await _getSvgImageFromAssets(context, svgAssetLink);
    final sizedSvgImage = await _getSizedSvgImage(svgImage);

    final pngSizedBytes = await sizedSvgImage.toByteData(format: ui.ImageByteFormat.png);
    final unit8List = pngSizedBytes.buffer.asUint8List();
    return BitmapDescriptor.fromBytes(unit8List);
  }

  static Future<BitmapDescriptor> getBitmapDescriptorFromSvgString(String svgString) async {
    final svgImage = await _getSvgImageFromString(svgString);
    final sizedSvgImage = await _getSizedSvgImage(svgImage);

    final pngSizedBytes = await sizedSvgImage.toByteData(format: ui.ImageByteFormat.png);
    final unit8List = pngSizedBytes.buffer.asUint8List();
    return BitmapDescriptor.fromBytes(unit8List);
  }

  static Future<ui.Image> _getSvgImageFromAssets(BuildContext context, String svgAssertLink) async {
    String svgString = await DefaultAssetBundle.of(context).loadString(svgAssertLink);
    DrawableRoot drawableRoot = svg.fromSvgString(svgString, null);
    ui.Picture picture = drawableRoot.toPicture();
    ui.Image image = await picture.toImage(
        drawableRoot.viewport.width.toInt(), drawableRoot.viewport.height.toInt());
    return image;
  }

  static Future<ui.Image> _getSvgImageFromString(String svgString) async {
    DrawableRoot drawableRoot = svg.fromSvgString(svgString, null);
    ui.Picture picture = drawableRoot.toPicture();
    ui.Image image = await picture.toImage(
        drawableRoot.viewport.width.toInt(), drawableRoot.viewport.height.toInt());
    return image;
  }

  static Future<ui.Image> _getSizedSvgImage(ui.Image svgImage) async {
    final size = 50 * ui.window.devicePixelRatio;
    final width = size;
    final height = width;

    final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);
    final Rect svgRect =
        Rect.fromLTRB(0.0, 0.0, svgImage.width.toDouble(), svgImage.height.toDouble());
    final Rect sizedRect = Rect.fromLTRB(0.0, 0.0, width, height); // owr size here
    canvas.drawImageRect(svgImage, svgRect, sizedRect, Paint());
    return await pictureRecorder.endRecording().toImage(width.toInt(), height.toInt());
  }
}

从您的小部件类:

final icon = await BitmapDescriptorHelper.getBitmapDescriptorFromSvgAsset(
                                      context, "assets/icons/some_svg_icon.svg");

      final Marker marker = Marker(
        icon: icon,
        ...
      );

享受:)

tyg4sfes

tyg4sfes3#

使用flutter_svg的最新版本(在我的例子中是2.0.1),您可以通过以下方式实现它:

class BitmapDescriptorHelper {
  
  static Future<BitmapDescriptor> getBitmapDescriptorFromSvgAsset(
    String assetName, [
    Size size = const Size(48, 48),
  ]) async {
    final pictureInfo = await vg.loadPicture(SvgAssetLoader(assetName), null);

    double devicePixelRatio = ui.window.devicePixelRatio;
    int width = (size.width * devicePixelRatio).toInt();
    int height = (size.height * devicePixelRatio).toInt();

    final scaleFactor = math.min(
      width / pictureInfo.size.width,
      height / pictureInfo.size.height,
    );

    final recorder = ui.PictureRecorder();

    ui.Canvas(recorder)
      ..scale(scaleFactor)
      ..drawPicture(pictureInfo.picture);

    final rasterPicture = recorder.endRecording();

    final image = rasterPicture.toImageSync(width, height);
    final bytes = (await image.toByteData(format: ui.ImageByteFormat.png))!;

    return BitmapDescriptor.fromBytes(bytes.buffer.asUint8List());
  }
}
3npbholx

3npbholx4#

我刚 checkout BitmapDescriptor类的文档。您可以尝试使用fromAssetImage()类方法
https://pub.dev/documentation/google_maps_flutter/latest/google_maps_flutter/BitmapDescriptor/fromAssetImage.html

相关问题