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

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

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

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

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

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

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

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

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

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

Maps SDK для библиотеки утилит iOS

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

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

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

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

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

  1. Щелкните файл Info.plist в Навигаторе проекта в Xcode, чтобы открыть редактор списка свойств.
  2. Нажмите значок «+» рядом с пунктом «Список информационных свойств», чтобы добавить новое свойство.
  3. В поле «ключ» введите «NSLocationWhenInUseUsageDescription». Xcode автоматически переведет это в длинное имя «Конфиденциальность — местоположение при использовании, описание использования». Полный список возможных свойств разрешения на определение местоположения см. в разделе «Запрос авторизации для служб определения местоположения» в документации Apple Developer.
  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)
    // ...
  }
  // ...
}
      

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