本頁面說明 Maps SDK for iOS 公用程式庫提供的標記叢集公用程式。
只要將標記叢集化,就算在地圖上放置大量標記,畫面也不會雜亂而難以瀏覽。標記叢集公用程式可協助您管理多個縮放等級不同的標記。
當使用者以高縮放等級查看時,地圖上會顯示個別標記;而縮小地圖時,標記會聚類為多個叢集,方便使用者查看地圖。
下列螢幕截圖顯示標記叢集的預設樣式:

以下是自訂標記叢集的範例:

必要條件和注意事項
Maps SDK for iOS 公用程式庫
標記叢集公用程式包含在 Maps SDK for iOS 公用程式庫。如果您尚未設定程式庫,請先按照設定指南的步驟完成設定,再閱讀本頁面的其他內容。
為獲得最佳效能,建議的標記數量上限為 10,000 個。
位置存取權
這個範例使用裝置的 GPS 找出使用者和座標上的地圖。如要啟用這項功能,您必須在專案的 Info.plist
檔案中為 NSLocationWhenInUseUsageDescription
權限新增說明。
如要新增這項功能,請按照下列步驟操作:
- 在 Xcode 中,按一下專案導覽器中的
Info.plist
檔案,即可開啟屬性清單編輯器。 - 按一下「資訊資源清單」旁邊的「+」圖示,即可新增資源。
- 在「key」欄位中,輸入「NSLocationWhenInUseUsageDescription」。Xcode 會自動將其轉譯為全名「隱私權 - 使用時位置說明」。如需可能的位置存取權屬性完整清單,請參閱 Apple 開發人員說明文件的「 要求定位服務授權」。
- 將「類型」欄位設定保留為「字串」。
- 在「值」欄位中,說明應用程式需要使用使用者位置資訊的原因。例如:「尋找使用者可提供附近的商家資訊。」
實作標記叢集
實作標記叢集需要三個步驟:
如要查看如何導入標記叢集的完整範例,請參閱 Objective-C 和 Swift 的 GitHub 範例應用程式。建立叢集管理員
如要使用叢集管理員,請執行下列操作:
- 設定算繪地圖的
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
的自訂實作方式。如要根據公用程式庫中這些通訊協定的實作範例來設定自訂實作,或者您也可以完成通訊協定,藉此編寫完全自訂的實作程式碼。