標記叢集

選取平台: Android iOS JavaScript

本頁面說明 Maps SDK for iOS 的公用程式庫所提供的標記叢集公用程式。

只要將標記叢集化,就算在地圖上放置大量標記,畫面也不會因而變得雜亂而難以瀏覽。標記叢集公用程式可協助您管理多個縮放等級不同的標記。

當使用者以高縮放等級查看時,地圖上會顯示個別標記;而縮小地圖時,標記會聚類為多個叢集,方便使用者查看地圖。

以下螢幕截圖顯示標記叢集的預設樣式:

含預設樣式叢集標記的地圖

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

含自訂叢集標記的地圖

必要條件和注意事項

Maps SDK for iOS 公用程式庫

標記叢集公用程式包含在 Maps SDK for iOS 公用程式庫。如果您尚未設定程式庫,請先按照設定指南的步驟完成設定,再閱讀本頁面的其他內容。

為獲得最佳成效,建議標記數量上限為 10,000。

位置存取權

本例使用裝置的 GPS,找出使用者座標的位置和地圖。如要啟用這項功能,您必須在專案 Info.plist 檔案的 NSLocationWhenInUseUsageDescription 權限中新增說明。

請按照下列步驟操作:

  1. 在 Xcode 的「專案導覽工具」中按一下 Info.plist 檔案,即可開啟屬性清單編輯器。
  2. 按一下「##99++'」圖示旁邊的「##99 資訊屬性」',即可新增資源。
  3. 在「#&99;key'」欄位中輸入「'NSLocationWhenInUseUsageDescription'」。Xcode 會自動將這個名稱轉換為長名稱 ' 隱私權 - 使用中的說明說明'。如需可用位置存取權屬性的完整清單,請參閱 Apple 開發人員說明文件中的要求定位服務授權
  4. 保留 'Type'欄位設定 'String'。
  5. 在「值'」欄位中,輸入應用程式需要使用使用者位置資訊的原因。例如:「定位使用者提供附近的商家資訊」。

實作標記叢集

導入標記叢集需要三個步驟:

  1. 建立叢集管理員。
  2. 將要建立叢集的標記傳遞至叢集叢集。
  3. 叫用叢集管理員
如需導入標記叢集的完整範例,請參閱「GitHub 上的 Objective-C 和 Swift 範例應用程式」。

建立叢集管理員

如要使用叢集管理員,請執行下列操作:

  1. 設定地圖算繪的 ViewController,以符合 GMSMapViewDelegate 通訊協定。
  2. 建立 GMUClusterManager 的執行個體。
  3. 將要導入標記叢集的 GMSMapView 執行個體,以及下列通訊協定的實作項目傳遞至 GMUClusterManager 例項:
    • GMUClusterIconGenerator:提供應用程式邏輯,用於擷取要在不同縮放等級中使用的叢集圖示。
    • GMUClusterAlgorithm:指定用來決定標記叢集行為的演算法,例如要納入同一個叢集的標記之間的距離。
    • GMUClusterRenderer:提供應用程式邏輯來處理地圖上叢集圖示的實際轉譯。
  4. GMUClusterManager 執行個體上設定地圖委派。

公用程式程式庫包含圖示產生器 (GMUDefaultClusterIconGenerator)、演算法 (GMUNonHierarchicalDistanceBasedAlgorithm) 和轉譯器 (GMUDefaultClusterRenderer) 的預設實作。您也可以選擇建立自己的自訂扣環圖示產生器、演算法和轉譯器。

以下程式碼會在 ViewControllerviewDidLoad 回呼中使用這些預設值建立叢集叢集:

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 上實作的任何事件。將所有剩餘事件轉送至地圖委派 (如有提供)。請注意,標準標記的事件 (也就是由叢集轉譯器產生的標記) 一律會轉送至地圖委派。

自訂標記叢集

您可以為 GMUClusterRendererGMUClusterIconGeneratorGMUClusterAlgorithm 提供自訂實作。您可以根據公用程式庫中的這些通訊協定的實作範例來自訂實作,也可以透過完成這些通訊協定編寫完全自訂的實作。