На этой странице описана утилита кластеризации маркеров, доступная в библиотеке утилит 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
. Вы можете основать свою собственную реализацию на примере реализации этих протоколов, включенном в библиотеку утилит, или вы можете запрограммировать полностью пользовательскую реализацию, выполнив протоколы.