Agrupación de marcadores en clústeres

Selecciona la plataforma: Android iOS JavaScript

En esta página, se describe la utilidad de agrupamiento de marcadores en clústeres que está disponible en la biblioteca de utilidades del SDK de Maps para iOS.

Cuando agrupas tus marcadores en clústeres, puedes incluir muchos marcadores en un mapa sin que esto dificulte su lectura. La utilidad de agrupamiento de marcadores en clústeres te ayuda a administrar varios marcadores con diferentes niveles de zoom.

Cuando un usuario visualiza el mapa con un alto nivel de zoom, aparecen los marcadores individuales. Cuando el usuario aleja el mapa, los marcadores se agrupan en clústeres para facilitar su visualización.

En la siguiente captura de pantalla se muestra el estilo predeterminado de los clústeres de marcadores:

Un mapa con marcadores agrupados en el estilo predeterminado

A continuación, se muestra un ejemplo de clústeres de marcadores personalizados:

Mapa con marcadores agrupados en clústeres personalizados

Requisitos previos y notas

Biblioteca de utilidades del SDK de Maps para iOS

La utilidad de agrupamiento de marcadores en clústeres forma parte de la Biblioteca de utilidades del SDK de Maps para iOS. Si aún no configuraste la biblioteca, sigue la guía de configuración antes de leer el resto de esta página.

Para obtener el mejor rendimiento, la cantidad máxima de marcadores es de 10.000.

Permiso de ubicación

En este ejemplo, se usa el GPS del dispositivo para ubicar al usuario y el mapa en sus coordenadas. Para habilitar esta opción, debes agregar una descripción al permiso NSLocationWhenInUseUsageDescription en el archivo Info.plist del proyecto.

Para agregar esta opción, haz lo siguiente:

  1. Haz clic en el archivo Info.plist en el navegador de proyectos de Xcode para abrir el editor de listas de propiedades.
  2. Haz clic en el ícono "+" junto a "Information Property List" para agregar una propiedad nueva.
  3. En el campo "key", escribe "NSLocationWhenInUseUsageDescription". Xcode traducirá automáticamente esto al nombre largo "Privacidad: Descripción del uso de la ubicación cuando se usa". Para obtener una lista completa de las propiedades de permiso de ubicación posibles, consulta Cómo solicitar autorización para los servicios de ubicación en la documentación para desarrolladores de Apple.
  4. Deja el campo "Tipo" establecido como "Cadena".
  5. En el campo "Valor", escribe una descripción del motivo por el que tu app requiere el uso de la ubicación del usuario. Por ejemplo, "Ubica al usuario para proporcionar fichas de empresas cercanas".

Implementa el agrupamiento de marcadores en clústeres

La implementación del agrupamiento de marcadores en clústeres requiere tres pasos:

  1. Crea una instancia del administrador de clústeres.
  2. Pasa los marcadores que deseas agrupar en clústeres al administrador de clústeres.
  3. Invoca el administrador de clústeres.
Para ver un ejemplo completo de cómo implementar el agrupamiento de marcadores en clústeres, consulta las apps de ejemplo en Objective-C y Swift en GitHub.

Crea el administrador de clústeres

Para usar el administrador de clústeres, haz lo siguiente:

  1. Configura el ViewController en el que se renderiza tu mapa para que se ajuste al protocolo GMSMapViewDelegate.
  2. Crea una instancia de GMUClusterManager.
  3. Pasa la instancia de GMSMapView en la que deseas implementar el agrupamiento de marcadores en clústeres y las implementaciones de los siguientes protocolos a la instancia de GMUClusterManager:
    • GMUClusterIconGenerator: Proporciona lógica de la aplicación que recupera los íconos de clúster que se usarán en los diferentes niveles de zoom.
    • GMUClusterAlgorithm: Especifica un algoritmo que determina el comportamiento de la forma en que se agrupan los marcadores, como la distancia entre los marcadores que se incluirán en el mismo clúster.
    • GMUClusterRenderer: Proporciona la lógica de la aplicación que controla la renderización real de los íconos de clúster en el mapa.
  4. Establece el delegado del mapa en la instancia de GMUClusterManager.

La biblioteca de utilidades incluye implementaciones predeterminadas del generador de íconos (GMUDefaultClusterIconGenerator), el algoritmo (GMUNonHierarchicalDistanceBasedAlgorithm) y el renderizador (GMUDefaultClusterRenderer). De manera opcional, puedes crear tu propio generador de íconos, algoritmo y renderizador de agrupamiento en clústeres personalizados.

El siguiente código crea un administrador de clústeres con estos valores predeterminados en la devolución de llamada 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
      

Cómo agregar marcadores

Existen dos formas de agregar marcadores al agrupador de marcadores: de forma individual o como un array.

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

Es un array 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];
      

Cómo invocar el agrupador de marcadores en clústeres

Una vez que hayas creado tu agrupador de marcadores en clústeres y le hayas pasado los marcadores que deseas agrupar, solo tienes que llamar al método cluster en tu instancia del agrupador de marcadores en clústeres.

Swift

clusterManager.cluster()
      

Objective-C

[_clusterManager cluster];
      

Administra eventos en marcadores y clústeres

En general, cuando usas el SDK de Maps para iOS, para escuchar eventos en el mapa, debes implementar el protocolo GMSMapViewDelegate. Puedes escuchar eventos del mapa, pero no puedes escuchar los eventos del administrador de clústeres con seguridad de tipos. Cuando el usuario presiona un marcador, un elemento de clúster individual o un clúster, la API activa mapView:didTapMarker: y adjunta los datos adicionales del clúster a la propiedad marker.userData. Luego, puedes verificar si userData cumple con el protocolo GMUCluster para determinar si se presionó un ícono de clúster o un marcador.

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

El administrador de clústeres ahora intercepta cualquier evento que hayas implementado en clusterManager. Reenvía los eventos restantes al delegado del mapa, si se proporciona. Ten en cuenta que los eventos para los marcadores estándar (es decir, los marcadores que no genera el renderizador de clústeres) siempre se reenvían al delegado del mapa.

Personaliza el agrupamiento de marcadores en clústeres

Puedes proporcionar una implementación personalizada para GMUClusterRenderer, GMUClusterIconGenerator o GMUClusterAlgorithm. Puedes basar tu implementación personalizada en la implementación de muestra de estos protocolos que se incluye en la biblioteca de utilidades, o bien puedes codificar una implementación completamente personalizada cumpliendo con los protocolos.