【问题标题】:How do we create custom marker icon in google map flutter我们如何在谷歌地图颤振中创建自定义标记图标
【发布时间】:2021-08-07 16:07:52
【问题描述】:

我正在使用谷歌地图来显示用户位置。我需要一个自定义标记来显示用户位置。用户图像是从 url 获取的。但是我无法获得如图所示形状的标记.我的代码在下面给出。我的代码无法实现所需的背景形状。任何人请帮助我。

 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


    【解决方案1】:

    首先定义标记

      static Set<Marker> markers = {};
    

    然后将此 Set 添加到 googleMapWidget

    GoogleMap(
      markers: markers,)
    

    每次您想要添加标记时都可以使用它

    setState(() {
      markers.add(Marker(
        markerId: MarkerId(lastMapPosition.toString()),
        position: lastMapPosition,
        icon: BitmapDescriptor.defaultMarker,
      ));
    });
    

    【讨论】:

    • 我可以在谷歌地图中显示标记。问题是我无法在图像周围实现类似形状的标记。
    • 用颤振实现这个图标很困难。这个网站可能会帮助你fluttershapemaker.com
    【解决方案2】:

    您可以尝试将小部件作为标记,说明如下:

    custom map marker

    更新

    添加 WidgetsBinding.instance.addPostFrameCallback

    【讨论】:

    • 谢谢..这行得通..我正在从网络加载内部图像。如果需要时间,它会加载占位符图像,并且已经创建了标记。有任何解决方案吗?
    • 请检查我下面的代码并帮助我改进..它工作正常。但我觉得它不是正确的方法。
    【解决方案3】:
           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}',
                                ),
                              ),
                            ),
                          )
                        ],
                      ),
                    ),
                  ),
                );
              }
            }
    

    【讨论】:

    • 这是我实现它的方式。在 initState 中,我设置了加载小部件和创建 markerIcon 的延迟。我们如何改进呢?
    • 你能做到吗?我的意思是以编程方式制作标记类型的形状...?
    猜你喜欢
    • 1970-01-01
    • 2020-01-13
    • 2020-06-26
    • 1970-01-01
    • 2019-06-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-29
    相关资源
    最近更新 更多