Flutter中google_maps_cluster_manager如何仅聚类特定类型标记?
仅聚类特定类型标记的解决方案
针对使用google_maps_cluster_manager时仅聚类特定类型标记的需求,提供两种可行方案:
方案一:外部分离处理(推荐,无需修改包源码)
这种方式不需要改动包内代码,通过在业务层分离需要聚类和不需要聚类的标记,分别管理:
扩展ClusterItem添加标识
给自定义的ClusterItem添加是否允许聚类的属性:class CustomClusterItem extends ClusterItem { final bool shouldCluster; CustomClusterItem({ required super.position, super.id, super.icon, this.shouldCluster = true, }); }分离标记列表
将所有标记分为两类,仅把需要聚类的交给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();初始化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(() {}); }在地图初始化时加载所有标记
在initState中调用_addNonClusterMarkers(),并绑定ClusterManager到地图相机事件:@override void initState() { super.initState(); _addNonClusterMarkers(); clusterManager.setMapId(GoogleMapController().mapId); }
方案二:修改包源码(需维护自定义分支)
如果你必须修改包内代码,需要修正之前的逻辑错误,确保不需要聚类的标记被保留:
给ClusterItem添加shouldCluster属性
在包的cluster_item.dart中添加属性:class ClusterItem<T> { // ...原有属性 final bool shouldCluster; ClusterItem({ required this.position, this.id, this.icon, this.shouldCluster = true, }); }修改_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
相关产品推荐
相关产品推荐

