マーカーをクラスタリングすることで、マップを見づらくすることなく、マップ上に多数のマーカーを配置できます。
はじめに
このビデオでは、マップ上に多数のデータポイントが必要な場合のマーカー クラスリングの使用について説明しています。
マーカー クラスタリング ユーティリティを使うと、異なるズームレベルにある複数のマーカーを管理できます。正確には、「マーカー」はこの時点では実際には「アイテム」で、レンダリングされるときに初めて「マーカー」になります。ただし、わかりやすくするために、このドキュメントでは一貫してこれらを「マーカー」と呼びます。
ユーザーが高いズームレベルでマップを表示すると、個別のマーカーがマップ上に表示されます。ユーザーがズームアウトすると、マーカーがまとまってクラスタになり、マップが見やすくなります。マーカー クラスタリング ユーティリティは、Maps SDK for Android ユーティリティ ライブラリに含まれています。ライブラリをまだセットアップしていない場合は、このページの残りを読む前に、設定ガイドに従ってセットアップしてください。
![クラスタリングされたマーカーのあるマップ](https://developers-dot-devsite-v2-prod.appspot.com/static/maps/documentation/android-sdk/images/utility-markercluster.png?authuser=6&hl=ja)
マーカー クラスタリング ユーティリティを使用するには、マーカーを ClusterItem
オブジェクトとして ClusterManager
に追加します。ClusterManager
はマーカーを Algorithm
に渡し、これによりマーカーが一連のクラスタに変換されます。ClusterRenderer
は、クラスタと個別のマーカーを追加および削除することで、レンダリングを行います。ClusterRenderer
と Algorithm
はプラグ可能で、カスタマイズできます。
ユーティリティ ライブラリには、マーカー クラスタリング ユーティリティのサンプル実装を提供するデモアプリが付属しています。デモアプリの実行方法については、設定ガイドをご覧ください。デモアプリには、次のマーカー クラスタリング サンプルが含まれています。
ClusteringDemoActivity
: マーカー クラスタリングを示す単純なアクティビティ。BigClusteringDemoActivity
: 2,000 個のマーカーのクラスタリング。CustomMarkerClusteringDemoActivity
: クラスタリングされたマーカーのカスタム デザインの作成。
単純なマーカー クラスタを追加する
次のステップに従って、10 個のマーカーからなる単純なクラスタを作成します。結果は以下のようになります。ただし、表示またはクラスタリングされているマーカーの数は、ズームレベルによって異なります。
![クラスタリングされた 10 個のマーカーを含むマップ](https://developers-dot-devsite-v2-prod.appspot.com/static/maps/documentation/android-sdk/images/utility-markercluster-simple.png?authuser=6&hl=ja)
iOS アプリの開発に必要な主なステップは次のとおりです。
- マップ上のマーカーを表すために、
ClusterItem
を実装します。クラスタ アイテムにより、マーカーの位置が LatLng オブジェクトとして返され、必要に応じてタイトルまたはスニペットが返されます。 - ズームレベルに基づいてクラスタ アイテム(マーカー)をグループ化するために、新しい
ClusterManager
を追加します。 ClusterManager
はリスナーを実装するため、マップのOnCameraIdleListener()
をClusterManager
に設定します。- マーカー クリック イベントへのレスポンスで特定の機能を追加する場合は、マップの
OnMarkerClickListener()
をClusterManager
に設定します。これは、ClusterManager
がリスナーを実装するためです。 - マーカーを
ClusterManager
に入力します。
次に、各ステップの詳細を示します。10 個のマーカーからなる単純なクラスタを作成するには、まず、ClusterItem
を実装する MyItem
クラスを作成します。
Java
public class MyItem implements ClusterItem { private final LatLng position; private final String title; private final String snippet; public MyItem(double lat, double lng, String title, String snippet) { position = new LatLng(lat, lng); this.title = title; this.snippet = snippet; } @Override public LatLng getPosition() { return position; } @Override public String getTitle() { return title; } @Override public String getSnippet() { return snippet; } @Nullable @Override public Float getZIndex() { return 0f; } }
Kotlin
inner class MyItem( lat: Double, lng: Double, title: String, snippet: String ) : ClusterItem { private val position: LatLng private val title: String private val snippet: String override fun getPosition(): LatLng { return position } override fun getTitle(): String { return title } override fun getSnippet(): String { return snippet } override fun getZIndex(): Float { return 0f } init { position = LatLng(lat, lng) this.title = title this.snippet = snippet } }
マップのアクティビティで、ClusterManager
を追加し、これにクラスタ アイテムを入力します。ClusterManager
が MyItem
型であることを宣言する型引数 <MyItem>
に注目してください。
Java
// Declare a variable for the cluster manager. private ClusterManager<MyItem> clusterManager; private void setUpClusterer() { // Position the map. map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(51.503186, -0.126446), 10)); // Initialize the manager with the context and the map. // (Activity extends context, so we can pass 'this' in the constructor.) clusterManager = new ClusterManager<MyItem>(context, map); // Point the map's listeners at the listeners implemented by the cluster // manager. map.setOnCameraIdleListener(clusterManager); map.setOnMarkerClickListener(clusterManager); // Add cluster items (markers) to the cluster manager. addItems(); } private void addItems() { // Set some lat/lng coordinates to start with. double lat = 51.5145160; double lng = -0.1270060; // Add ten cluster items in close proximity, for purposes of this example. for (int i = 0; i < 10; i++) { double offset = i / 60d; lat = lat + offset; lng = lng + offset; MyItem offsetItem = new MyItem(lat, lng, "Title " + i, "Snippet " + i); clusterManager.addItem(offsetItem); } }
Kotlin
// Declare a variable for the cluster manager. private lateinit var clusterManager: ClusterManager<MyItem> private fun setUpClusterer() { // Position the map. map.moveCamera(CameraUpdateFactory.newLatLngZoom(LatLng(51.503186, -0.126446), 10f)) // Initialize the manager with the context and the map. // (Activity extends context, so we can pass 'this' in the constructor.) clusterManager = ClusterManager(context, map) // Point the map's listeners at the listeners implemented by the cluster // manager. map.setOnCameraIdleListener(clusterManager) map.setOnMarkerClickListener(clusterManager) // Add cluster items (markers) to the cluster manager. addItems() } private fun addItems() { // Set some lat/lng coordinates to start with. var lat = 51.5145160 var lng = -0.1270060 // Add ten cluster items in close proximity, for purposes of this example. for (i in 0..9) { val offset = i / 60.0 lat += offset lng += offset val offsetItem = MyItem(lat, lng, "Title $i", "Snippet $i") clusterManager.addItem(offsetItem) } }
ズームインとズームアウト時のクラスタリング アニメーションを無効にすることもできます。
アニメーションをオフにすると、クラスタへの移行が切り替わるのではなく、マーカーが所定の位置に切り替わります。
アニメーションを無効にするには、以下のように ClusterManager
で setAnimation()
を使用します。
Java
clusterManager.setAnimation(false);
Kotlin
clusterManager.setAnimation(false)
クラスタ化した個別のマーカー用の情報ウィンドウを追加する
クラスタ化した特定のマーカー用の情報ウィンドウを追加するには、ClusterItem
の実装のコンストラクタにタイトルとスニペットの文字列を追加します。
以下の例では、タイトルとスニペットを設定して、情報ウィンドウを含むマーカーを addItems()
メソッドに追加しています。
Java
// Set the lat/long coordinates for the marker. double lat = 51.5009; double lng = -0.122; // Set the title and snippet strings. String title = "This is the title"; String snippet = "and this is the snippet."; // Create a cluster item for the marker and set the title and snippet using the constructor. MyItem infoWindowItem = new MyItem(lat, lng, title, snippet); // Add the cluster item (marker) to the cluster manager. clusterManager.addItem(infoWindowItem);
Kotlin
// Set the lat/long coordinates for the marker. val lat = 51.5009 val lng = -0.122 // Set the title and snippet strings. val title = "This is the title" val snippet = "and this is the snippet." // Create a cluster item for the marker and set the title and snippet using the constructor. val infoWindowItem = MyItem(lat, lng, title, snippet) // Add the cluster item (marker) to the cluster manager. clusterManager.addItem(infoWindowItem)
マーカー クラスタをカスタマイズする
ClusterManager
コンストラクタでは DefaultClusterRenderer
と NonHierarchicalDistanceBasedAlgorithm
を作成します。ClusterRenderer
と Algorithm
は、ClusterManager
の setAlgorithm(Algorithm<T> algorithm)
メソッドと setRenderer(ClusterRenderer<T> view)
メソッドを使って変更できます。
ClusterRenderer
を実装すると、クラスタのレンダリングをカスタマイズできます。DefaultClusterRenderer
は、開始点として適しています。DefaultClusterRenderer
をサブクラス化することで、デフォルトをオーバーライドできます。
カスタマイズの詳細な例については、ユーティリティ ライブラリに付属のデモアプリにある CustomMarkerClusteringDemoActivity
をご覧ください。
![クラスタリングされたカスタム マーカーを含むマップ](https://developers-dot-devsite-v2-prod.appspot.com/static/maps/documentation/android-sdk/images/utility-markercluster-custom.png?authuser=6&hl=ja)
CustomMarkerClusteringDemoActivity
は独自のクラスタ アイテムである Person
を定義し、DefaultClusterRenderer
を PersonRenderer
として拡張することで、このアイテムをレンダリングします。
デモでは、ClusterManager.OnClusterClickListener<Person>
インターフェースを実装して、クラスタがクリックされたときに、その人に関する詳細情報を表示する方法も示されています。ClusterManager.OnClusterItemClickListener<Person>
も同様の方法で実装できます。
デモアプリの実行方法については、設定ガイドをご覧ください。