Кластеризация маркеров позволяет добавить на карту много маркеров и сделать так, чтобы все ее данные легко читались.
Введение
В этом видеоролике рассказывается о кластеризации маркеров, которая требуется в случае, если на карте нужно отобразить много данных одновременно.
Утилита для кластеризации маркеров позволяет управлять несколькими маркерами на разных уровнях масштабирования. При этом маркеры фактически обрабатываются как объекты, а отрисовываются как маркеры. Однако для ясности в этой статье всегда используется термин "маркеры".
Когда пользователь просматривает карту в большом масштабе, на ней отображаются отдельные маркеры. При уменьшении масштаба маркеры собираются в кластеры, что упрощает чтение карты. Утилита для кластеризации маркеров входит в состав библиотеки утилит Maps SDK для Android. Если вы ещё не настроили эту библиотеку, выполните рекомендации из руководства по настройке, прежде чем продолжить чтение этой страницы.
![Карта с кластеризованными маркерами](https://developers.google.cn/static/maps/documentation/android-sdk/images/utility-markercluster.png?authuser=3&hl=ru)
Чтобы воспользоваться утилитой кластеризации маркеров, необходимо добавить маркеры в виде объектов ClusterItem
в ClusterManager
. ClusterManager
передает маркеры в Algorithm
, который преобразует их в набор кластеров. ClusterRenderer
отвечает за отрисовку, с его помощью добавляются и удаляются кластеры и отдельные маркеры. Классы ClusterRenderer
и Algorithm
являются подключаемыми модулями, и их можно настраивать.
В комплект библиотеки утилит входит демонстрационное приложение, в котором приведены примеры реализации утилиты для кластеризации маркеров. О том, как запустить демонстрационное приложение, рассказывается в руководстве по настройке. Демонстрационное приложение включает в себя следующие примеры кластеризации маркеров:
ClusteringDemoActivity
– простая операция, демонстрирующая кластеризацию маркеров.BigClusteringDemoActivity
– кластеризация 2000 маркеров.CustomMarkerClusteringDemoActivity
– создание собственного макета для кластеризованных маркеров.
Как добавить простое средство кластеризации маркеров
Чтобы создать простой кластер, состоящий из 10 маркеров, выполните описанные ниже действия. Результат будет иметь следующий вид, хотя количество отображаемых и кластеризованных маркеров будет изменяться в зависимости от уровня масштабирования:
![Карта с 10 кластеризованными маркерами](https://developers.google.cn/static/maps/documentation/android-sdk/images/utility-markercluster-simple.png?authuser=3&hl=ru)
Ниже перечислены шаги, которые необходимо выполнить.
- Реализуйте класс
ClusterItem
для представления маркеров на карте. Объект кластера возвращает позицию маркера в виде объекта LatLng. Он также может возвращать название или фрагмент (необязательно). - Добавьте новый объект
ClusterManager
, группирующий объекты кластеров (маркеры) с учетом уровня масштабирования. - Свяжите метод
OnCameraIdleListener()
карты с объектомClusterManager
. Это нужно сделать, потому что вClusterManager
реализован прослушиватель. - Если вы хотите добавить функции, срабатывающие при клике по маркеру, нужно связать метод
OnMarkerClickListener()
карты с объектомClusterManager
, поскольку вClusterManager
реализован прослушиватель. - Передайте маркеры объекту
ClusterManager
.
Подробные инструкции. Чтобы создать простой кластер из десяти маркеров, сначала создайте класс MyItem
, реализующий ClusterItem
.
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 } }
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; } }
В операции, работающей с картой, добавьте ClusterManager
и передайте ему объекты кластеров. Обратите внимание на аргумент типа <MyItem>
, декларирующий ClusterManager
как относящийся к типу MyItem
.
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) } }
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); } }
Вы также можете отключить анимацию кластеров при увеличении и уменьшении масштаба.
Если анимация отключена, маркеры мгновенно перемещаются на нужные позиции, а не передвигаются в кластеры или из кластеров.
Чтобы отключить анимацию, используйте метод setAnimation()
в ClusterManager
, как показано здесь:
Kotlin
clusterManager.setAnimation(false)
Java
clusterManager.setAnimation(false);
Как добавить информационное окно для отдельного кластеризованного маркера
Чтобы добавить информационное окно для конкретных кластеризованных маркеров, добавьте строки title (название) и snippet (фрагмент) в конструктор вашего класса ClusterItem
.
В следующем примере показано, как реализовать в методе addItems()
добавление маркера с информационным окном, задав значения полей title и snippet:
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)
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);
Как настроить кластеры маркеров
Конструктор класса ClusterManager
создает объекты DefaultClusterRenderer
и NonHierarchicalDistanceBasedAlgorithm
. Вы можете изменить ClusterRenderer
и Algorithm
с помощью методов setAlgorithm(Algorithm<T> algorithm)
и setRenderer(ClusterRenderer<T> view)
класса ClusterManager
.
Вы можете реализовать ClusterRenderer
, чтобы изменить настройки отображения кластеров. В качестве исходного макета рекомендуется использовать DefaultClusterRenderer
. Создав подкласс на основе DefaultClusterRenderer
, вы можете изменить настройки по умолчанию.
Подробный пример настройки представлен в операции CustomMarkerClusteringDemoActivity
демонстрационного приложения из библиотеки утилит.
![Карта с настраиваемой кластеризацией маркеров](https://developers.google.cn/static/maps/documentation/android-sdk/images/utility-markercluster-custom.png?authuser=3&hl=ru)
В CustomMarkerClusteringDemoActivity
определяется объект кластера Person
и реализуется его отрисовка за счет наследования класса DefaultClusterRenderer
как PersonRenderer
.
В демонстрационном приложении также показано, как реализовать интерфейс ClusterManager.OnClusterClickListener<Person>
для отображения дополнительной информации о человеке (элементе Person) при клике по кластеру. Вы также можете реализовать ClusterManager.OnClusterItemClickListener<Person>
аналогичным образом.
О том, как запустить демонстрационное приложение, рассказывается в руководстве по настройке.