我们如何在谷歌地图flutter中创建自定义标记图标

问题描述 投票:0回答:5

我正在使用谷歌地图来显示用户位置。我需要一个自定义标记来显示用户位置。用户图像是从网址获取的。但我无法获得像图像中所示的形状的标记。我的代码如下。使用我的代码,我无法实现所需的背景形状。有人请帮我解决这个问题。

 Future<void> getMarkerIcon(String imagePath, Size size) async {
    final ui.PictureRecorder pictureRecorder = ui.PictureRecorder();
    final Canvas canvas = Canvas(pictureRecorder);

    final Radius radius = Radius.circular(size.width / 2);

    final Paint tagPaint = Paint()..color = Utils.myColor.primary;
    final double tagWidth = 20.0;

    final Paint shadowPaint = Paint()..color = Colors.white;
    final double shadowWidth = 2.0;

    final Paint borderPaint = Paint()..color = Colors.white;
    final double borderWidth = 2.0;

    final double imageOffset = shadowWidth + borderWidth;

    // Add shadow circle
    canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromLTWH(0.0, 0.0, size.width, 100),
          topLeft: radius,
          topRight: radius,
          bottomLeft: radius,
          bottomRight: radius,
        ),
        shadowPaint);

    // Add border circle
    canvas.drawRRect(
        RRect.fromRectAndCorners(
          Rect.fromLTWH(
              shadowWidth, shadowWidth, size.width - (shadowWidth * 2), 100),
          topLeft: radius,
          topRight: radius,
          bottomLeft: radius,
          bottomRight: radius,
        ),
        borderPaint);

    // Oval for the image
    Rect oval = Rect.fromLTWH(imageOffset, imageOffset,
        size.width - (imageOffset * 2), size.height - (imageOffset * 2));

    // Add path for oval image
    canvas.clipPath(Path()..addOval(oval));

    // Add image
    ui.Image image = await getImageFromPath(
        imagePath); // Alternatively use your own method to get the image
    paintImage(canvas: canvas, image: image, rect: oval, fit: BoxFit.fitWidth);

    // Convert canvas to image
    final ui.Image markerAsImage =
        await pictureRecorder.endRecording().toImage(size.width.toInt(), 100);

    // Convert image to bytes
    final ByteData byteData =
        await markerAsImage.toByteData(format: ui.ImageByteFormat.png);
    final Uint8List uint8List = byteData.buffer.asUint8List();
    setState(() {
      markerIcon = BitmapDescriptor.fromBytes(uint8List);
    });
  }

  Future<ui.Image> getImageFromPath(String imagePath) async {
    File imageFile = await DefaultCacheManager().getSingleFile(imagePath);

    Uint8List imageBytes = imageFile.readAsBytesSync();

    final Completer<ui.Image> completer = new Completer();

    ui.decodeImageFromList(imageBytes, (ui.Image img) {
      return completer.complete(img);
    });

    return completer.future;
  }
flutter google-maps flutter-layout
5个回答
2
投票

查看 https://pub.dev/packages/custom_map_markers 将任何小部件渲染为标记。使用小部件可能会更容易实现您想要的特定外观


0
投票
       class _PostedMapState extends State<PostedMap> {
          Completer<GoogleMapController> _mapController = Completer();
          Uint8List imageDataBytes;
          var markerIcon;
          GlobalKey iconKey = GlobalKey();
        
          @override
          void initState() {
            super.initState();
//            if (widget.userImage != '') {
//              Future.delayed(Duration(seconds: 5), () {
//                getCustomMarkerIcon(iconKey);
//              });
//            }
WidgetsBinding.instance.addPostFrameCallback(getCustomMarkerIcon(iconKey));
          }
        
          @override
          Widget build(BuildContext context) {
            // TODO: implement build.
            return Container(
              height: widget.height,
              width: widget.width,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.all(Radius.circular(10)),
              ),
              // margin: EdgeInsets.only(left: 20, right: 20),
              child: Stack(
                children: [
                  getMarkerWidget(),
                  Card(
                    child: GoogleMap(
                      mapType: MapType.normal,
                      onTap: (x) {
                        MapsLauncher.launchCoordinates(
                            widget.checkInLat.toDouble(), widget.checkInLon.toDouble());
                      },
                      zoomControlsEnabled: false,
                      zoomGesturesEnabled: false,
                      mapToolbarEnabled: false,
                      trafficEnabled: false,
                      tiltGesturesEnabled: false,
                      scrollGesturesEnabled: false,
                      rotateGesturesEnabled: false,
                      myLocationEnabled: false,
                      liteModeEnabled: false,
                      indoorViewEnabled: false,
                      initialCameraPosition: CameraPosition(
                        target: LatLng(
                          double.parse(widget.checkInLat),
                          double.parse(widget.checkInLon),
                        ),
                        zoom: 14.4746,
                      ),
                      onMapCreated: (GoogleMapController controller) {
                        controller.setMapStyle(mapStyle);
                        // _mapController = controller;
                        try {
                          _mapController.complete(controller);
                        } catch (err) {
                          Log.e("err", err);
                        }
                      },
                      myLocationButtonEnabled: false,
                      markers: Set<Marker>.of(
                        <Marker>[
                          Marker(
                              draggable: false,
                              markerId: MarkerId(widget.userImage),
                              position: LatLng(double.parse(widget.checkInLat),
                                  double.parse(widget.checkInLon)),
                              // icon: currentLocationIcon,
                              icon: markerIcon ?? BitmapDescriptor.defaultMarker),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            );
          }
        
          Future<void> getCustomMarkerIcon(GlobalKey iconKey) async {
            RenderRepaintBoundary boundary = iconKey.currentContext.findRenderObject();
            ui.Image image = await boundary.toImage(pixelRatio: 3.0);
            ByteData byteData = await image.toByteData(format: ui.ImageByteFormat.png);
            var pngBytes = byteData.buffer.asUint8List();
            setState(() {
              markerIcon = BitmapDescriptor.fromBytes(pngBytes);
            });
          }
        
          getMarkerWidget() {
            return Transform.translate(
              offset: Offset(50, 50),
              child: RepaintBoundary(
                key: iconKey,
                child: SizedBox(
                  height: 40,
                  width: 40,
                  child: Stack(
                    children: [
                      Container(
                        decoration: BoxDecoration(
                          image: DecorationImage(
                            image: AssetImage(
                                '${ASSETS.assetImage("/map_pin_icon2.png")}'),
                            fit: BoxFit.fitHeight,
                          ),
                        ),
                      ),
                      Positioned(
                        left: 5,
                        top: 6,
                        child: ClipOval(
                          child: Container(
                            width: 20,
                            height: 20,
                            child: CommonWidgets().buildCachedNetworkImage(
                              '${widget.userImage}',
                            ),
                          ),
                        ),
                      )
                    ],
                  ),
                ),
              ),
            );
          }
        }

0
投票

您可以尝试制作widget作为标记,说明如下:

自定义地图标记

已更新

添加WidgetsBinding.instance.addPostFrameCallback


0
投票

尝试使用这个在线工具。这些对我帮助很大。 shapemaker.web.app


0
投票

这不是100%的你的要求,也许有帮助

//为旅行计划地图创建自定义标记 未来 createMarkerWithCustomIcon(String imageUrl, LatLng 位置, 字符串标记标题、函数()? onTap) 异步 { 最终 BitmapDescriptor 自定义图标 = 等待 getMarkerIcon(imageUrl, Size(150, 150));

最终标记标记 = 标记( 标记 ID: 标记 ID(标记标题), 位置: 位置, 图标:自定义图标, 点按:点按, );

返回标记; }

Future getMarkerIcon(String imageUrl, Size size) async { 最终 ui.PictureRecorder pictureRecorder = ui.PictureRecorder(); 最终 Canvas 画布 = Canvas(pictureRecorder); 最终 Radius 半径 = Radius.circular(size.width / 2);

最终绘制shadowPaint = Paint()..color = Colors.white.withAlpha(100); 最终双阴影宽度 = 15.0;

最终Paint borderPaint = Paint()..color = Colors.white; 最终双边框宽度 = 3.0;

最终双图像偏移=shadowWidth + borderWidth;

//阴影圈 画布.drawRRect( RRect.fromRectAndCorners( 矩形.fromLTWH(0.0, 0.0, 尺寸.宽度, 尺寸.高度), 左上角:半径, 右上角:半径, 左下角:半径, 右下角:半径, ), 阴影绘画);

//边框圆 画布.drawRRect( RRect.fromRectAndCorners( Rect.fromLTWH(shadowWidth, ShadowWidth, size.width - (shadowWidth * 2), 尺寸.高度 - (shadowWidth * 2)), 左上角:半径, 右上角:半径, 左下角:半径, 右下角:半径, ), 边框绘制);

// 图像的椭圆形 矩形椭圆 = Rect.fromLTWH(imageOffset, imageOffset, size.width - (imageOffset * 2), size.height - (imageOffset * 2));

// 剪切图像的椭圆形路径 canvas.clipPath(Path()..addOval(椭圆形));

// 获取并绘制网络图像 ui.Image 图像=等待_fetchNetworkImage(imageUrl); PaintImage(画布:画布,图像:图像,矩形:椭圆形,适合:BoxFit.cover);

// 将画布转换为图像 最终 ui.ImagemarkerAsImage = 等待 pictureRecorder .endRecording() .toImage(size.width.toInt(), size.height.toInt());

// 将图像转换为字节 最终的字节数据?字节数据 = 等待markerAsImage.toByteData(格式:ui.ImageByteFormat.png); 最终 Uint8List uint8List = byteData!.buffer.asUint8List();

返回 BitmapDescriptor.fromBytes(uint8List); }

未来 _fetchNetworkImage(String imageUrl) 异步 { 最终http.Response响应=等待http.get(Uri.parse(imageUrl)); 最终 Uint8List imageBytes = response.bodyBytes; 最终 ui.Codec 编解码器=等待 ui.instantiateImageCodec(imageBytes); 最终 ui.FrameInfo fi = 等待 codec.getNextFrame(); 返回 fi.image; }

© www.soinside.com 2019 - 2024. All rights reserved.