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

Flutter使用Mapbox实现点击地图放置Marker的方案

Flutter + Mapbox 点击放置Marker 实现方案

以下实现基于官方维护的mapbox_maps_flutter稳定版封装,无第三方额外依赖,体验与原生渲染一致。

前置准备

  • 在项目pubspec.yaml中添加依赖:
dependencies:
  flutter:
    sdk: flutter
  mapbox_maps_flutter: ^2.3.0
  • 提前完成Mapbox Access Token基础配置:Android端在AndroidManifest.xml配置token字段,iOS端在Info.plist添加对应配置,确保地图可正常加载。

核心实现逻辑

整个功能只需要3步即可跑通,不建议用Stack层叠组件覆盖地图的方式实现假Marker,会出现缩放不同步、性能差的问题,直接用Mapbox原生的点标注API实现即可:

  • 地图初始化完成后创建点标注管理器,绑定地图点击事件
  • 触发地图点击时,拿到点击位置的经纬度坐标
  • 调用点标注管理器的添加方法,在对应坐标位置渲染Marker

可直接运行的核心代码

import 'package:flutter/material.dart';
import 'package:mapbox_maps_flutter/mapbox_maps_flutter.dart';

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

  @override
  State<MapMarkerPage> createState() => _MapMarkerPageState();
}

class _MapMarkerPageState extends State<MapMarkerPage> {
  late MapboxMap mapboxController;
  PointAnnotationManager? _annotationManager;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text("点击放置Marker")),
      body: MapboxWidget(
        accessToken: "替换为你自己的Mapbox Access Token",
        onMapCreated: _onMapCreated,
        initialCameraOptions: CameraOptions(
          center: Point(coordinates: Position(116.3974, 39.9093)),
          zoom: 12,
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.clear_all),
        onPressed: () async {
          // 清空所有已添加的Marker
          await _annotationManager?.deleteAll();
        },
      ),
    );
  }

  void _onMapCreated(MapboxMap controller) async {
    mapboxController = controller;
    // 初始化点标注管理器
    _annotationManager = await controller.annotations.createPointAnnotationManager();

    // 监听地图点击事件
    controller.onMapTap.add((event) {
      final clickPosition = Point(
        coordinates: Position(event.coordinate.lng, event.coordinate.lat),
      );
      _addMarker(clickPosition);
    });
  }

  Future<void> _addMarker(Point position) async {
    if (_annotationManager == null) return;
    // 添加Marker,可自定义图标、大小、偏移量等参数
    await _annotationManager!.create(
      PointAnnotationOptions(
        geometry: position,
        iconImage: "mapbox-marker-icon-red", // 内置红色Marker图标,可替换为自定义图片
        iconSize: 1.0,
        iconAnchor: IconAnchor.BOTTOM, // 图标锚点设为底部,精准对准点击坐标
      ),
    );
  }

  @override
  void dispose() {
    mapboxController.onMapTap.clear();
    _annotationManager?.dispose();
    super.dispose();
  }
}

自定义扩展说明

  • 如果需要使用自定义图标作为Marker,提前调用mapboxController.style.addStyleImage方法将本地资源图注册到地图样式,再把iconImage参数替换为注册时自定义的图片ID即可
  • 需要响应Marker点击事件的话,给_annotationManager设置onPointAnnotationTap回调即可,可在回调中触发弹窗、页面跳转等逻辑
  • 如果需要持久化Marker,只需要把存储Marker坐标的列表存到本地存储,下次进入页面重新遍历添加即可

内容的提问来源于stack exchange,提问作者Omar Sayed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 04:48:15