Кластеризация маркеров

Выберите платформу: Android iOS JavaScript

На этой странице описывается утилита для кластеризации маркеров, доступная в библиотеке утилит для SDK карт для iOS .

Группируя маркеры, вы можете разместить на карте большое количество маркеров, не затрудняя её чтение. Утилита кластеризации маркеров помогает управлять несколькими маркерами на разных уровнях масштабирования.

При высоком уровне масштабирования на карте отображаются отдельные маркеры. При уменьшении масштаба маркеры объединяются в группы, что облегчает просмотр карты.

На следующем снимке экрана показан стиль кластеров маркеров по умолчанию:

Карта с группами маркеров в стиле по умолчанию.

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

Карта с пользовательскими сгруппированными маркерами.

Предварительные требования и примечания

Библиотека вспомогательных инструментов для SDK карт iOS

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

Для достижения наилучших результатов рекомендуется использовать максимальное количество маркеров — 10 000.

Разрешение на определение местоположения

В этом примере для определения местоположения пользователя и карты по их координатам используется GPS устройства. Чтобы включить эту функцию, необходимо добавить описание к разрешению NSLocationWhenInUseUsageDescription в файле Info.plist проекта.

Чтобы добавить это, выполните следующие действия:

  1. Чтобы открыть редактор списков свойств, щелкните файл Info.plist в навигаторе проекта в Xcode.
  2. Нажмите значок «+» рядом с «Список объектов недвижимости», чтобы добавить новый объект.
  3. В поле «ключ» введите «NSLocationWhenInUseUsageDescription». Xcode автоматически преобразует это в полное название «Privacy - Location When In Use Usage Description». Полный список возможных свойств разрешений для определения местоположения см. в разделе «Запрос авторизации для служб определения местоположения» в документации Apple для разработчиков.
  4. Оставьте поле «Тип» со значением «Строка».
  5. В поле «Значение» укажите причину, по которой вашему приложению требуется использовать местоположение пользователя. Например: «Определяет местоположение пользователя для предоставления списка ближайших предприятий».

Реализация кластеризации маркеров

Реализация кластеризации маркеров включает три этапа:

  1. Создайте экземпляр менеджера кластера.
  2. Передайте менеджеру кластера маркеры, которые вы хотите объединить в кластер.
  3. Запустите менеджер кластера.
Чтобы увидеть полный пример реализации кластеризации маркеров, ознакомьтесь с примерами приложений на Objective-C и Swift на GitHub .

Создание менеджера кластера

Для использования менеджера кластера выполните следующие действия:

  1. Настройте ViewController , в котором отображается ваша карта, в соответствии с протоколом GMSMapViewDelegate .
  2. Создайте экземпляр GMUClusterManager .
  3. Передайте экземпляр GMSMapView , в котором вы хотите реализовать кластеризацию маркеров, а также реализации следующих протоколов экземпляру GMUClusterManager :
    • GMUClusterIconGenerator : Предоставляет логику приложения, которая извлекает значки кластера для использования на разных уровнях масштабирования.
    • GMUClusterAlgorithm : Задает алгоритм, определяющий поведение кластеризации маркеров, например, расстояние между маркерами, которые следует включить в один кластер.
    • GMUClusterRenderer : Предоставляет логику приложения, которая обрабатывает фактическое отображение значков кластеров на карте.
  4. Установите делегат карты для экземпляра 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)
    // ...
  }
  // ...
}
      

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
      

Добавление маркеров

Добавить маркеры в кластеризатор маркеров можно двумя способами: по отдельности или в виде массива.

Индивидуальный маркер

Быстрый

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

Массив маркеров

Быстрый

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

Вызов кластеризатора маркеров

После того как вы создали кластеризатор маркеров и передали ему маркеры, которые хотите сгруппировать, вам остается только вызвать метод cluster в экземпляре вашего кластеризатора маркеров.

Быстрый

clusterManager.cluster()
      

Objective-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
}
      

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 . Оставшиеся события он пересылает делегату карты, если он предоставлен. Обратите внимание, что события для стандартных маркеров (то есть маркеров, не сгенерированных рендерером кластера) всегда пересылаются делегату карты.

Настройка кластеризации маркеров

Вы можете предоставить собственную реализацию для GMUClusterRenderer , GMUClusterIconGenerator или GMUClusterAlgorithm . Вы можете основывать свою собственную реализацию на примерах реализации этих протоколов, включенных в библиотеку утилит, или же написать полностью собственную реализацию, выполнив необходимые протоколы.