Clustering de marcadores

Selecione a plataforma: Android iOS JavaScript

Esta página descreve o utilitário de clustering de marcadores disponível na biblioteca de utilitários do SDK do Maps para iOS.

Com o clustering de marcadores, você pode colocar um grande número de marcadores em um mapa sem dificultar a leitura. O utilitário de clustering de marcadores ajuda a gerenciar vários marcadores em diferentes níveis de zoom.

Quando um usuário vê um mapa com bastante zoom, os marcadores individuais aparecem no mapa. Quando o usuário diminui o zoom, os marcadores se reúnem em clusters, facilitando a visualização.

A captura de tela a seguir mostra o estilo padrão dos clusters de marcadores:

Um mapa com marcadores agrupados no estilo padrão

Abaixo está um exemplo de clusters de marcadores personalizados:

Mapa com marcadores em cluster personalizados

Pré-requisitos e observações

Biblioteca de utilitários do SDK do Maps para iOS

O utilitário de clustering de marcadores faz parte da Biblioteca de utilitários do SDK do Maps para iOS. Se você ainda não configurou a biblioteca, siga o guia antes de ler o restante desta página.

Para obter o melhor desempenho, o número máximo recomendado de marcadores é 10.000.

Permissão de localização

Este exemplo usa o GPS do dispositivo para localizar o usuário e o mapa nas coordenadas dele. Para ativar isso, adicione uma descrição à permissão NSLocationWhenInUseUsageDescription no arquivo Info.plist do projeto.

Para adicionar isso, faça o seguinte:

  1. Clique no arquivo Info.plist no navegador de projetos do Xcode para abrir o Editor de lista de propriedades.
  2. Clique no ícone "+" ao lado de "Lista de propriedades de informações" para adicionar uma propriedade.
  3. No campo "key", digite "NSLocationWhenInUseUsageDescription". O Xcode vai traduzir automaticamente isso para o nome longo "Privacy - Location When In Use Usage Description". Para uma lista completa de propriedades possíveis de permissão de localização, consulte Solicitar autorização para Serviços de localização na documentação para desenvolvedores da Apple.
  4. Deixe o campo "Tipo" definido como "String".
  5. No campo "Valor", digite uma descrição do motivo pelo qual o app precisa usar a localização do usuário. Por exemplo, "Localiza o usuário para fornecer informações de empresas próximas".

Implementar o clustering de marcadores

A implementação do clustering de marcadores é feita em três etapas:

  1. Crie uma instância do gerenciador de cluster.
  2. Transmita os marcadores que você quer agrupar ao gerenciador de clusters.
  3. Invocar o gerenciador de clusters.
Para conferir um exemplo completo de como implementar o clustering de marcadores, consulte os apps de exemplo em Objective-C e Swift no GitHub.

Como criar o gerenciador de clusters

Para usar o gerenciador de clusters, faça o seguinte:

  1. Defina o ViewController em que o mapa é renderizado para obedecer ao protocolo GMSMapViewDelegate.
  2. Crie uma instância de GMUClusterManager.
  3. Transmita a instância de GMSMapView em que você quer implementar o clustering de marcadores e as implementações dos seguintes protocolos para a instância GMUClusterManager:
    • GMUClusterIconGenerator: fornece lógica de aplicativo que busca os ícones de cluster a serem usados em diferentes níveis de zoom.
    • GMUClusterAlgorithm: especifica um algoritmo que determina o comportamento do cluster, como a distância entre os marcadores que serão incluídos.
    • GMUClusterRenderer: fornece a lógica do aplicativo que processa a renderização real dos ícones de cluster no mapa.
  4. Defina o delegado do mapa na instância GMUClusterManager.

A biblioteca de utilitários inclui implementações padrão do gerador de ícones (GMUDefaultClusterIconGenerator), algoritmo (GMUNonHierarchicalDistanceBasedAlgorithm) e renderizador (GMUDefaultClusterRenderer). Você também pode criar seu próprio gerador de ícones, algoritmo e renderizador de clustering personalizados.

O código a seguir cria um gerenciador de clusters usando esses padrões no callback viewDidLoad de ViewController:

Swift

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
      

Adicionar marcadores

Há duas maneiras de adicionar marcadores ao cluster de marcadores: individualmente ou como uma matriz.

Marcador individual

Swift

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

Matriz de marcadores

Swift

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

Como invocar o clusterer de marcadores

Depois de criar o clustering de marcadores e transmitir os marcadores que você quer agrupar, basta chamar o método cluster na instância do clustering de marcadores.

Swift

clusterManager.cluster()
      

Objective-C

[_clusterManager cluster];
      

Tratamento de eventos em marcadores e grupos

Em geral, ao usar o SDK do Maps para iOS, para ouvir eventos no mapa, é necessário implementar o protocolo GMSMapViewDelegate. É possível ouvir eventos de mapa, mas não os eventos do gerenciador de clusters com segurança de tipos. Quando o usuário toca em um marcador, um item de cluster individual ou um cluster, a API aciona mapView:didTapMarker: e anexa os dados extras do cluster à propriedade marker.userData. Em seguida, é possível verificar se userData está em conformidade com o protocolo GMUCluster para determinar se um ícone de cluster ou um marcador foi tocado.

Swift

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

O gerenciador de clusters agora intercepta todos os eventos implementados em clusterManager e encaminha os eventos restantes para o delegado do mapa, se fornecido. Os eventos de marcadores padrão (ou seja, marcadores não gerados pelo renderizador de cluster) são sempre encaminhados para o delegado do mapa.

Personalizar o clustering de marcadores

Você pode fornecer uma implementação personalizada para GMUClusterRenderer, GMUClusterIconGenerator ou GMUClusterAlgorithm. É possível basear sua implementação personalizada na implementação de amostra desses protocolos incluída na biblioteca de utilitários ou codificar uma implementação totalmente personalizada seguindo os protocolos.