マーカー クラスタリング

プラットフォームを選択: 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. 新しいプロパティを追加するには '+' 'Information Property List' の横にあるアイコンをクリックします。
  3. 'key' フィールドに、'NSLocationWhenInUseUsageDescription' と入力します。Xcode は、これを長い名前の「プライバシー - 使用状況に関する説明を位置情報の使用説明」に自動的に変換します。位置情報の利用許可プロパティの完全なリストについては、Apple のデベロッパー向けドキュメントの位置情報サービスの承認リクエストをご覧ください。
  4. 'Type'フィールドは ' String'に設定したままにします。
  5. ' Value' フィールドに、アプリでユーザーの位置情報を使用する必要がある理由の説明を入力します。例: 「このユーザーを近くのビジネス リスティングに案内します。」

マーカー クラスタリングを実装する

マーカー クラスタリングを実装するには、以下の 3 つの手順を行います。

  1. クラスタ マネージャー インスタンスを作成します。
  2. クラスタ化したいマーカーをクラスタ マネージャーに渡します。
  3. クラスタ マネージャーを呼び出します。
マーカー クラスタリングの実装方法の完全な例については、Objective-C と Swift の GitHub にあるサンプルアプリをご確認ください。

クラスタ マネージャーの作成

クラスタ マネージャーを使用する手順は次のとおりです。

  1. GMSMapViewDelegate プロトコルに準拠するように地図をレンダリングする ViewController を設定します。
  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
      

マーカーを追加する

マーカー クラスタにマーカーを追加するには、個別または配列の 2 つの方法があります。

個別のマーカー

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];
      

Marker Clusterer の呼び出し

Marker Clusterer を作成してクラスタ化したいマーカーを渡したら、Marker Clusterer インスタンスに対して cluster メソッドを呼び出します。

Swift

clusterManager.cluster()
      

Objective-C

[_clusterManager cluster];
      

マーカーおよびクラスター上のイベントを処理する

Maps SDK for iOS を使用する場合、通常は、地図上でイベントをリッスンするために、GMSMapViewDelegate プロトコルを実装する必要があります。マップイベントはリッスンできますが、タイプセーフなクラスタ マネージャー イベントをリッスンすることはできません。ユーザーがマーカー、個々のクラスタ アイテム、またはクラスタをタップすると、API が mapView:didTapMarker: をトリガーし、追加のクラスタデータを marker.userData プロパティに追加します。その後、userDataGMUCluster プロトコルに準拠しているかどうかを確認し、クラスタ アイコンとマーカーがタップされたかどうかを確認できます。

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 のカスタム実装を指定できます。カスタム ライブラリは、ユーティリティ ライブラリに含まれているこれらのプロトコルのサンプル実装をベースにすることも、プロトコルを実装して完全にカスタム実装をコーディングすることもできます。