You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Flutter中制作带网络图片的自定义动态Google Map标记

在Flutter中实现带网络图片的自定义Google Map标记

步骤1:添加依赖

在pubspec.yaml中引入所需包:

dependencies:
  flutter:
    sdk: flutter
  google_maps_flutter: ^2.5.0
  cached_network_image: ^3.3.0 # 用于缓存网络图片,优化加载体验

步骤2:实现自定义标记生成方法

将网络图片转换成Google Map标记支持的BitmapDescriptor,同时添加圆形底色匹配你需要的效果:

import 'dart:async';
import 'dart:typed_data';
import 'dart:ui' as ui;

import 'package:cached_network_image/cached_network_image.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

Future<BitmapDescriptor> createCustomMarker(String imageUrl) async {
  final recorder = ui.PictureRecorder();
  final canvas = Canvas(recorder);

  // 绘制白色圆形背景
  final bgPaint = Paint()..color = Colors.white;
  canvas.drawCircle(const Offset(40, 40), 40, bgPaint);

  // 加载网络图片
  final imageProvider = CachedNetworkImageProvider(imageUrl);
  final imageCompleter = Completer<ui.Image>();
  imageProvider.resolve(const ImageConfiguration()).addListener(
    ImageStreamListener((info, _) => imageCompleter.complete(info.image)),
  );
  final ui.Image image = await imageCompleter.future;

  // 将图片裁剪为圆形并绘制
  final rect = Rect.fromLTWH(10, 10, 60, 60);
  final rRect = RRect.fromRectAndRadius(rect, const Radius.circular(30));
  canvas.clipRRect(rRect);
  canvas.drawImage(image, const Offset(10, 10), Paint());

  // 转换为BitmapDescriptor
  final picture = recorder.endRecording();
  final markerImage = await picture.toImage(80, 80);
  final byteData = await markerImage.toByteData(format: ui.ImageByteFormat.png);
  return BitmapDescriptor.fromBytes(byteData!.buffer.asUint8List());
}

步骤3:在地图中使用自定义标记

初始化地图控制器,加载自定义标记并添加到地图上:

class CustomMarkerMap extends StatefulWidget {
  const CustomMarkerMap({super.key});

  @override
  State<CustomMarkerMap> createState() => _CustomMarkerMapState();
}

class _CustomMarkerMapState extends State<CustomMarkerMap> {
  final _mapController = Completer<GoogleMapController>();
  final Set<Marker> _markers = {};

  static const _initialCamera = CameraPosition(
    target: LatLng(37.42796, -122.08575),
    zoom: 14.5,
  );

  @override
  void initState() {
    super.initState();
    _loadMarkers();
  }

  Future<void> _loadMarkers() async {
    // 替换为你的网络图片地址
    final markerIcon = await createCustomMarker("https://example.com/avatar.jpg");
    setState(() {
      _markers.add(
        Marker(
          markerId: const MarkerId("user_marker"),
          position: const LatLng(37.42796, -122.08575),
          icon: markerIcon,
          infoWindow: const InfoWindow(title: "用户位置"),
        ),
      );
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: GoogleMap(
        initialCameraPosition: _initialCamera,
        markers: _markers,
        onMapCreated: (controller) => _mapController.complete(controller),
      ),
    );
  }
}

注意事项

  • 确保项目配置了网络权限:
    • Android:在AndroidManifest.xml中添加 <uses-permission android:name="android.permission.INTERNET"/>
    • iOS:在Info.plist中添加网络权限配置(允许任意域名或指定域名)
  • 可根据需求调整标记的大小、背景颜色、边框等样式,修改画布绘制逻辑即可
  • 如果不需要图片缓存,可替换CachedNetworkImageProvider为NetworkImage,但前者能更好处理加载失败、占位图等场景

内容的提问来源于stack exchange,提问作者Michael Solomon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 21:46:06