本页介绍了 Maps SDK for iOS 的实用程序库中提供的标记聚类实用程序。
通过将标记聚类,即使在地图上放置大量标记,也不会使地图变得难以查看。标记聚类实用程序可帮助您管理不同缩放级别的多个标记。
当用户以较高的放大倍数查看地图时,各个标记会在地图上显示。当用户缩小地图时,这些标记会聚拢形成聚类,以方便用户查看地图。
下面的屏幕截图显示了标记聚类的默认样式:

下面是一个自定义标记聚类的示例:

前提条件和说明
Maps SDK for iOS 实用程序库
标记聚类实用程序包含在 Maps SDK for iOS 实用程序库中。如果您尚未设置该库,请先按照设置指南操作,然后再阅读本页面的其余内容。
为获得最佳性能,建议的最大标记数量为 10,000。
位置权限
此示例使用设备的 GPS 在其坐标上定位用户和地图。如需启用此功能,您必须在项目的 Info.plist
文件中为 NSLocationWhenInUseUsageDescription
权限添加说明。
如需添加此功能,请执行以下操作:
- 点击 Xcode 中的 Project Navigator 中的
Info.plist
文件,打开属性列表编辑器。 - 点击“信息属性列表”旁边的 &+39 图标以添加新属性。
- 在 'key' 字段中,输入 &NS39;NSLocationWhenInUseUsageDescription'。Xcode 会自动将其翻译成长标题“Privacy - Location Use In Use UsageDescription”。如需查看可能的位置信息权限属性的完整列表,请参阅 Apple 开发者文档中的请求位置信息服务授权。
- 将 &Type 字段保留为 &String。
- 在“值”字段中,输入应用需要使用用户位置的原因说明。例如,“定位用户以提供附近的商家信息”。
实现标记聚类
实现标记聚类需要三个步骤:
如需查看有关如何实现标记聚类的完整示例,请查看 GitHub 上的 Objective-C 和 Swift 示例应用。创建集群管理器
如需使用集群管理器,请执行以下操作:
- 设置渲染地图的
ViewController
以符合GMSMapViewDelegate
协议。 - 创建
GMUClusterManager
的实例。 - 将您要实现标记聚类的
GMSMapView
实例和以下协议的实现传递给GMUClusterManager
实例:GMUClusterIconGenerator
:提供应用逻辑,用于提取要在不同缩放级别使用的集群图标。GMUClusterAlgorithm
:指定一种算法,用于确定标记聚类的行为,例如要在同一聚类中包含的标记之间的距离。GMUClusterRenderer
:提供处理地图上聚类图标实际渲染情况的应用逻辑。
- 在
GMUClusterManager
实例上设置地图委托。
实用程序库包含图标生成器 (GMUDefaultClusterIconGenerator
)、算法 (GMUNonHierarchicalDistanceBasedAlgorithm
) 和渲染程序 (GMUDefaultClusterRenderer
) 的默认实现。您也可以选择创建自己的自定义伪代码图标生成器、算法和渲染程序。
以下代码会在 ViewController
的 viewDidLoad
回调中使用这些默认值创建集群管理器:
Swift
import GoogleMaps import GoogleMapsUtils class MarkerClustering: UIViewController, GMSMapViewDelegate { private var mapView: GMSMapView! private var clusterManager: GMUClusterManager! override func viewDidLoad() { super.viewDidLoad() // Set up the cluster manager with the supplied icon generator and // renderer. let iconGenerator = GMUDefaultClusterIconGenerator() let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm() let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator) clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer) // Register self to listen to GMSMapViewDelegate events. clusterManager.setMapDelegate(self) // ... } // ... }
Objective-C
@import GoogleMaps; @import GoogleMapsUtils; @interface MarkerClustering () <GMSMapViewDelegate> @end @implementation MarkerClustering { GMSMapView *_mapView; GMUClusterManager *_clusterManager; } - (void)viewDidLoad { [super viewDidLoad]; // Set up the cluster manager with a supplied icon generator and renderer. id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init]; id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init]; id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:iconGenerator]; _clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer]; // Register self to listen to GMSMapViewDelegate events. [_clusterManager setMapDelegate:self]; // ... } // ... @end
添加标记
向标记聚类器添加标记的方法有两种:单独添加或数组添加。
单个标记
Swift
let position = CLLocationCoordinate2D(latitude: 47.60, longitude: -122.33) let marker = GMSMarker(position: position) clusterManager.add(marker)
Objective-C
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(47.60, -122.33); GMSMarker *marker = [GMSMarker markerWithPosition:position]; [_clusterManager addItem:marker];
标记数组
Swift
let position1 = CLLocationCoordinate2D(latitude: 47.60, longitude: -122.33) let marker1 = GMSMarker(position: position1) let position2 = CLLocationCoordinate2D(latitude: 47.60, longitude: -122.46) let marker2 = GMSMarker(position: position2) let position3 = CLLocationCoordinate2D(latitude: 47.30, longitude: -122.46) let marker3 = GMSMarker(position: position3) let position4 = CLLocationCoordinate2D(latitude: 47.20, longitude: -122.23) let marker4 = GMSMarker(position: position4) let markerArray = [marker1, marker2, marker3, marker4] clusterManager.add(markerArray)
Objective-C
CLLocationCoordinate2D position1 = CLLocationCoordinate2DMake(47.60, -122.33); GMSMarker *marker1 = [GMSMarker markerWithPosition:position1]; CLLocationCoordinate2D position2 = CLLocationCoordinate2DMake(47.60, -122.46); GMSMarker *marker2 = [GMSMarker markerWithPosition:position2]; CLLocationCoordinate2D position3 = CLLocationCoordinate2DMake(47.30, -122.46); GMSMarker *marker3 = [GMSMarker markerWithPosition:position3]; CLLocationCoordinate2D position4 = CLLocationCoordinate2DMake(47.20, -122.23); GMSMarker *marker4 = [GMSMarker markerWithPosition:position4]; NSArray<GMSMarker *> *markerArray = @[marker1, marker2, marker3, marker4]; [_clusterManager addItems:markerArray];
调用标记聚类器
创建标记聚类器并向其传递您希望聚类的标记后,您只需对标记聚类器实例调用 cluster
方法即可。
Swift
clusterManager.cluster()
Objective-C
[_clusterManager cluster];
处理标记和聚类上的事件
一般情况下,使用 Maps SDK for iOS 时,如需实现地图上的事件,您必须实现 GMSMapViewDelegate
协议。您可以监听地图事件,但无法监听类型安全的集群管理器事件。当用户点按标记、单个聚类项或聚类时,该 API 会触发 mapView:didTapMarker:
并将额外的聚类数据附加到 marker.userData
属性。然后,您可以检查 userData
是否符合 GMUCluster
协议,以确定是否已点按聚类图标或标记。
Swift
func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool { // center the map on tapped marker mapView.animate(toLocation: marker.position) // check if a cluster icon was tapped if marker.userData is GMUCluster { // zoom in on tapped cluster mapView.animate(toZoom: mapView.camera.zoom + 1) NSLog("Did tap cluster") return true } NSLog("Did tap a normal marker") return false }
Objective-C
- (BOOL)mapView:(GMSMapView *)mapView didTapMarker:(GMSMarker *)marker { // center the map on tapped marker [_mapView animateToLocation:marker.position]; // check if a cluster icon was tapped if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) { // zoom in on tapped cluster [_mapView animateToZoom:_mapView.camera.zoom + 1]; NSLog(@"Did tap cluster"); return YES; } NSLog(@"Did tap marker in cluster"); return NO; }
现在,集群管理器会拦截您在 clusterManager
上实现的所有事件。它会将任何剩余事件转发给地图委托(如果提供)。请注意,标准标记的事件(即,不是由集群渲染程序生成的标记)将始终转发到地图委托。
自定义标记聚类
您可以为 GMUClusterRenderer
、GMUClusterIconGenerator
或 GMUClusterAlgorithm
提供自定义实现。您可以根据实用程序库中包含的这些协议的示例实现来自定义实现,也可以通过实现协议来编码完全自定义的实现。