На этой странице описывается утилита кластеризации маркеров, доступная в библиотеке утилит для Maps SDK для iOS .
Сгруппировав маркеры, вы можете разместить на карте большое количество маркеров, не делая карту трудночитаемой. Утилита кластеризации маркеров помогает управлять несколькими маркерами с разными уровнями масштабирования.
Когда пользователь просматривает карту с высоким уровнем масштабирования, на карте отображаются отдельные маркеры. Когда пользователь уменьшает масштаб, маркеры собираются в кластеры, чтобы упростить просмотр карты.
На следующем снимке экрана показан стиль кластеров маркеров по умолчанию:

Ниже приведен пример пользовательских кластеров маркеров:

Предпосылки и примечания
Maps SDK для библиотеки утилит iOS
Утилита кластеризации маркеров входит в Maps SDK for iOS Utility Library . Если вы еще не настроили библиотеку, следуйте руководству по установке, прежде чем читать оставшуюся часть этой страницы.
Для наилучшей производительности рекомендуемое максимальное количество маркеров составляет 10 000.
Разрешение на местоположение
В этом примере используется GPS устройства для определения местоположения пользователя и карты по его координатам. Чтобы включить это, вы должны добавить описание к разрешению NSLocationWhenInUseUsageDescription
в файле Info.plist
проекта.
Чтобы добавить это, сделайте следующее:
- Щелкните файл
Info.plist
в навигаторе проекта в Xcode, чтобы открыть редактор списка свойств. - Щелкните значок «+» рядом с «Списком информационных свойств», чтобы добавить новое свойство.
- В поле «ключ» введите «NSLocationWhenInUseUsageDescription». Xcode автоматически переведет это в длинное имя «Конфиденциальность — местоположение при использовании, описание использования». Полный список возможных свойств разрешения местоположения см. в разделе «Запрос авторизации для служб определения местоположения » в документации Apple Developer.
- В поле «Тип» оставьте значение «Строка».
- В поле «Значение» введите описание причины, по которой вашему приложению требуется использование местоположения пользователя. Например, «Находит пользователя для предоставления списков ближайших компаний».
Реализация кластеризации маркеров
Реализация кластеризации маркеров состоит из трех шагов:
- Создайте экземпляр диспетчера кластера.
- Передайте маркеры, которые вы хотите сгруппировать, в диспетчер кластеров.
- Вызовите диспетчер кластера.
Создание менеджера кластера
Чтобы использовать менеджер кластера, сделайте следующее:
- Установите
ViewController
в котором отображается ваша карта, в соответствии с протоколомGMSMapViewDelegate
. - Создайте экземпляр
GMUClusterManager
. - Передайте экземпляр
GMSMapView
, в котором вы хотите реализовать кластеризацию маркеров, и реализации следующих протоколов экземпляруGMUClusterManager
:-
GMUClusterIconGenerator
: предоставляет логику приложения, которая извлекает значки кластера для использования на разных уровнях масштабирования. -
GMUClusterAlgorithm
: задает алгоритм, определяющий поведение кластеризации маркеров, например расстояние между маркерами, включаемое в один и тот же кластер. -
GMUClusterRenderer
: предоставляет логику приложения, которая обрабатывает фактическую визуализацию значков кластера на карте.
-
- Установите делегат карты в экземпляре
GMUClusterManager
.
Библиотека утилит включает стандартные реализации генератора значков ( GMUDefaultClusterIconGenerator
), алгоритма ( GMUNonHierarchicalDistanceBasedAlgorithm
) и средства визуализации ( GMUDefaultClusterRenderer
). При желании вы можете создать свой собственный генератор значков кластеризации, алгоритм и средство визуализации.
Следующий код создает менеджер кластера, используя эти значения по умолчанию в viewDidLoad
ViewController
:
Быстрый
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) // ... } // ... }
Цель-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
Добавление маркеров
Есть два способа добавить маркеры в кластеризатор маркеров: по отдельности или в виде массива.
Индивидуальный маркер
Быстрый
let position = CLLocationCoordinate2D(latitude: 47.60, longitude: -122.33) let marker = GMSMarker(position: position) clusterManager.add(marker)
Цель-C
CLLocationCoordinate2D position = CLLocationCoordinate2DMake(47.60, -122.33); GMSMarker *marker = [GMSMarker markerWithPosition:position]; [_clusterManager addItem:marker];
Массив маркеров
Быстрый
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)
Цель-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
на вашем экземпляре кластеризатора маркеров.
Быстрый
clusterManager.cluster()
Цель-C
[_clusterManager cluster];
Обработка событий маркеров и кластеров
Как правило, при использовании Maps SDK для iOS для прослушивания событий на карте необходимо реализовать протокол GMSMapViewDelegate
. Вы можете прослушивать события карты , но вы не можете прослушивать события менеджера кластера с безопасным типом. Когда пользователь касается маркера, отдельного элемента кластера или кластера, API запускает mapView:didTapMarker:
и прикрепляет дополнительные данные кластера к свойству marker.userData
. Затем вы можете проверить, соответствуют ли userData
протоколу GMUCluster
, чтобы определить, был ли нажат значок кластера или маркер.
Быстрый
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 }
Цель-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
. Вы можете создать свою пользовательскую реализацию на примере реализации этих протоколов, включенной в служебную библиотеку, или вы можете закодировать полностью пользовательскую реализацию, выполнив протоколы.