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

Flutter MapBox如何为集群添加onClick地图缩放事件?

Flutter MapBox 集群点击缩放实现方案

核心思路

集群是GeoJSON生成的特殊Feature,会自带point_count属性,我们可以通过监听地图要素点击事件,判断点击对象是否为集群,再执行缩放逻辑。

具体实现步骤

  1. 监听要素点击事件
    使用controller.onFeatureTapped监听所有可交互要素的点击,回调会返回点击的图层ID、对应的Feature对象和点击坐标。

  2. 识别集群要素
    判断Feature的properties中是否包含point_count字段,若包含则说明点击的是集群。

  3. 执行缩放逻辑
    获取集群的经纬度坐标,结合当前地图缩放等级计算目标缩放等级(比如当前等级+1,或直接设置为clusterMaxZoom - 1确保集群展开),最后调用moveCamera完成地图缩放。

修改后的完整代码示例

Future<void> addGeojsonCluster() async {
  var geojson = {
    "type": "FeatureCollection",
    "crs": { "type": "name", "properties": { "name": "pois" } },
    "features": [
      for(var marker in markers){
        "type" : "Feature", "properties" : {"id" : marker.title}, "geometry": {"type" : "Point", "coordinates" : [marker.longitude, marker.latitude] }
      },
    ]
  };

  await controller.addSource(
      "poi",
      GeojsonSourceProperties(
          data: geojson,
          cluster: true,
          clusterMaxZoom: 14, // Max zoom to cluster points on
          clusterRadius: 50,  // Radius of each cluster when clustering points (defaults to 50)
      )
  );

  // 确保集群圆圈图层开启交互
  await controller.addLayer(
      "poi",
      "poi-circles",
      const CircleLayerProperties(
          circleColor: [
            Expressions.step,
            [Expressions.get, 'point_count'],
            '#51bbd6', //blue
            100,
            '#f1f075', //yellow
            750,
            '#f28cb1' //pink
          ],
          circleRadius: [
        Expressions.step,
        [Expressions.get, 'point_count'],
        20,
        100,
        30,
        750,
        40
      ]),
      enableInteraction: true,
  );

  await controller.addSymbolLayer(
    "poi",
    "unclustered-point",
    const SymbolLayerProperties(
      textField: [Expressions.get, "id"],
      textHaloWidth: 1,
      textSize: 12.5,
      textHaloColor: '#ffffff',
      textOffset: [
        Expressions.literal,
        [0, 2]
      ],
      iconImage: "images/mapbox_circle_marker.png",
      iconSize: 2,
      iconAllowOverlap: true,
      textAllowOverlap: true,
      textColor: '#000000',
      textHaloBlur: 1,
    ),
    filter: [
      '!',
      ['has', 'point_count']
    ],
    enableInteraction: true,
  );
  
  // 集群数字层开启交互,点击数字也能触发缩放
  await controller.addLayer(
      "poi",
      "poi-count",
      const SymbolLayerProperties(
        textField: [Expressions.get, 'point_count_abbreviated'],
        textFont: ['DIN Offc Pro Medium', 'Arial Unicode MS Bold'],
        textSize: 12,
      ),
      enableInteraction: true,
  );

  // 添加集群点击缩放逻辑
  controller.onFeatureTapped.add((layerId, feature, point) {
    // 判断是否为集群要素
    if (feature.properties.containsKey('point_count')) {
      // 解析集群坐标(GeoJSON格式为[经度, 纬度],需转换为LatLng)
      final coords = feature.geometry['coordinates'] as List<double>;
      final clusterLatLng = LatLng(coords[1], coords[0]);

      // 获取当前相机位置,计算目标缩放等级
      controller.getCameraPosition().then((camera) {
        // 方案1:当前缩放等级+1,逐步展开集群
        final targetZoom = camera.zoom + 1;
        // 方案2:直接缩放到集群解散的前一级(clusterMaxZoom -1)
        // final targetZoom = 13;
        
        controller.moveCamera(CameraUpdate.newLatLngZoom(clusterLatLng, targetZoom));
      });
    }
  });
}

补充说明

  • 如果只想监听集群圆圈图层的点击,可以改用controller.onCircleTapped,但需要指定监听的图层ID为poi-circles,不如onFeatureTapped通用(后者能覆盖集群数字层的点击)。
  • 确保所有涉及集群的图层都设置了enableInteraction: true,否则点击事件不会触发。

内容的提问来源于stack exchange,提问作者Rémy Albanese

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 09:20:24