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

Flutter中google_maps_cluster_manager如何仅聚类特定类型标记?

仅聚类特定类型标记的解决方案

针对使用google_maps_cluster_manager时仅聚类特定类型标记的需求,提供两种可行方案:

方案一:外部分离处理(推荐,无需修改包源码)

这种方式不需要改动包内代码,通过在业务层分离需要聚类和不需要聚类的标记,分别管理:

  1. 扩展ClusterItem添加标识
    给自定义的ClusterItem添加是否允许聚类的属性:

    class CustomClusterItem extends ClusterItem {
      final bool shouldCluster;
    
      CustomClusterItem({
        required super.position,
        super.id,
        super.icon,
        this.shouldCluster = true,
      });
    }
    
  2. 分离标记列表
    将所有标记分为两类,仅把需要聚类的交给ClusterManager:

    // 你的全量标记列表
    final allItems = <CustomClusterItem>[
      CustomClusterItem(position: LatLng(31.2, 121.5), shouldCluster: true),
      CustomClusterItem(position: LatLng(31.2, 121.51), shouldCluster: false),
      // ...其他标记
    ];
    
    // 分离需要聚类和不需要聚类的项
    final clusterableItems = allItems.where((item) => item.shouldCluster).toList();
    final nonClusterableItems = allItems.where((item) => !item.shouldCluster).toList();
    
  3. 初始化ClusterManager并管理标记

    // 仅传入需要聚类的项初始化ClusterManager
    final clusterManager = ClusterManager<CustomClusterItem>(
      clusterableItems,
      _updateClusterMarkers,
      markerBuilder: (cluster) {
        // 自定义聚类标记的构建逻辑
        return Marker(
          markerId: MarkerId('cluster_${cluster.id}'),
          position: cluster.position,
          icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueBlue),
          infoWindow: InfoWindow(title: cluster.items.length.toString()),
        );
      },
    );
    
    // 存储所有地图标记的Map
    final Map<MarkerId, Marker> _markers = {};
    
    // 添加非聚类标记到地图
    void _addNonClusterMarkers() {
      for (var item in nonClusterableItems) {
        final marker = Marker(
          markerId: MarkerId('item_${item.id}'),
          position: item.position,
          icon: BitmapDescriptor.defaultMarkerWithHue(BitmapDescriptor.hueRed),
        );
        _markers[marker.markerId] = marker;
      }
    }
    
    // 更新聚类标记的回调
    void _updateClusterMarkers(List<Marker> markers) {
      // 移除旧的聚类标记
      _markers.removeWhere((key, _) => key.value.startsWith('cluster_'));
      // 添加新的聚类标记
      for (var marker in markers) {
        _markers[marker.markerId] = marker;
      }
      setState(() {});
    }
    
  4. 在地图初始化时加载所有标记
    在initState中调用_addNonClusterMarkers(),并绑定ClusterManager到地图相机事件:

    @override
    void initState() {
      super.initState();
      _addNonClusterMarkers();
      clusterManager.setMapId(GoogleMapController().mapId);
    }
    

方案二:修改包源码(需维护自定义分支)

如果你必须修改包内代码,需要修正之前的逻辑错误,确保不需要聚类的标记被保留:

  1. 给ClusterItem添加shouldCluster属性
    在包的cluster_item.dart中添加属性:

    class ClusterItem<T> {
      // ...原有属性
      final bool shouldCluster;
    
      ClusterItem({
        required this.position,
        this.id,
        this.icon,
        this.shouldCluster = true,
      });
    }
    
  2. 修改_computeClusters方法逻辑
    在cluster_manager.dart的_computeClusters方法开头,先分离并添加不需要聚类的标记,再对剩余项执行聚类:

    List<Cluster<T>> _computeClusters(
      List<ClusterItem<T>> inputItems,
      List<Cluster<T>> markerItems, {
      int level = 12,
    }) {
      // 先处理不需要聚类的项,直接作为单个标记加入
      final nonClusterItems = inputItems.where((i) => !i.shouldCluster).toList();
      markerItems.addAll(nonClusterItems.map((item) => Cluster<T>([item])));
    
      // 仅对需要聚类的项执行聚类逻辑
      final clusterableItems = inputItems.where((i) => i.shouldCluster).toList();
    
      if (clusterableItems.isEmpty) {
        return markerItems;
      }
    
      // 原有聚类逻辑,替换为clusterableItems
      String nextGeohash = clusterableItems[0].geohash.substring(0, level);
    
      List<ClusterItem<T>> items = clusterableItems
          .where((p) => p.geohash.substring(0, level) == nextGeohash)
          .toList();
    
      markerItems.add(Cluster<T>(items));
    
      List<ClusterItem<T>> newInputList = List.from(clusterableItems.where((i) =>
          i.geohash.substring(0, level) != nextGeohash));
    
      return _computeClusters(newInputList, markerItems, level: level);
    }
    

为什么之前的修改失效?

你之前的代码只在递归时保留了shouldCluster的项,但没有把不需要聚类的项添加到markerItems中,导致这部分标记被丢弃;同时输入列表被过滤后可能为空,打断了聚类递归流程,最终失去聚类功能。

内容的提问来源于stack exchange,提问作者raagull sakthivel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 21:57:11