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

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

必要條件和注意事項
Maps SDK for iOS 公用程式庫
標記叢集公用程式包含在 Maps SDK for iOS 公用程式庫。如果您尚未設定程式庫,請先按照設定指南的步驟完成設定,再閱讀本頁面的其他內容。
為獲得最佳成效,建議標記數量上限為 10,000。
位置存取權
本例使用裝置的 GPS,找出使用者座標的位置和地圖。如要啟用這項功能,您必須在專案 Info.plist
檔案的 NSLocationWhenInUseUsageDescription
權限中新增說明。
請按照下列步驟操作:
- 在 Xcode 的「專案導覽工具」中按一下
Info.plist
檔案,即可開啟屬性清單編輯器。 - 按一下「##99++'」圖示旁邊的「##99 資訊屬性」',即可新增資源。
- 在「#&99;key'」欄位中輸入「'NSLocationWhenInUseUsageDescription'」。Xcode 會自動將這個名稱轉換為長名稱 ' 隱私權 - 使用中的說明說明'。如需可用位置存取權屬性的完整清單,請參閱 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
提供自訂實作。您可以根據公用程式庫中的這些通訊協定的實作範例來自訂實作,也可以透過完成這些通訊協定編寫完全自訂的實作。