Grupowanie znaczników

Wybierz platformę: Android iOS JavaScript

Na tej stronie opisujemy narzędzie do grupowania znaczników, które jest dostępne w bibliotece narzędzi pakietu Maps SDK na iOS.

Dzięki grupowaniu znaczników możesz umieścić na mapie dużą liczbę znaczników, nie powodując, że mapa będzie czytelna. Narzędzie do grupowania znaczników ułatwia zarządzanie wieloma znacznikami na różnych poziomach powiększenia.

Gdy użytkownik wyświetla mapę w dużym powiększeniu, poszczególne znaczniki są widoczne na mapie. Gdy użytkownik pomniejsza mapę, znaczniki zbierają się w klastry, aby ułatwić przeglądanie mapy.

Zrzut ekranu poniżej pokazuje domyślny styl klastrów znaczników:

Mapa ze zgrupowanymi znacznikami w stylu domyślnym

Poniżej znajdziesz przykład niestandardowych klastrów znaczników:

Mapa z niestandardowymi znacznikami klastrami

Wymagania wstępne i uwagi

Biblioteka narzędziowa pakietu Maps SDK na iOS

Narzędzie do grupowania znaczników jest częścią biblioteki narzędziowej pakietu Maps SDK na iOS. Jeśli nie masz jeszcze skonfigurowanej biblioteki, zapoznaj się z pozostałą częścią tej strony, postępując zgodnie z przewodnikiem po konfiguracji.

Aby uzyskać najlepszą skuteczność, zalecana maksymalna liczba znaczników to 10 tys.

Dostęp do lokalizacji

W tym przykładzie używany jest GPS urządzenia, aby zlokalizować użytkownika i mapę na jego współrzędnych. Aby włączyć tę funkcję, musisz dodać opis do uprawnienia NSLocationWhenInUseUsageDescription w pliku Info.plist projektu.

Aby to dodać, wykonaj te czynności:

  1. Kliknij plik Info.plist w usłudze Project Navigator w Xcode, aby otworzyć edytor listy usług.
  2. Kliknij ikonę „+” obok pozycji „Lista właściwości informacji”, aby dodać nową właściwość.
  3. W polu „key” (klucz) wpisz „NSLocationWhenInUseUsageDescription”. Xcode automatycznie przetłumaczy to na długą nazwę „Privacy - Location when In Use Usage Description” (Prywatność – lokalizacja podczas używania). Pełną listę możliwych właściwości dostępu do lokalizacji znajdziesz w sekcji Prośba o autoryzację dla usług lokalizacyjnych w dokumentacji dla deweloperów Apple.
  4. W polu „Typ” pozostaw ustawienie „Ciąg”.
  5. W polu „Wartość” wpisz opis, dlaczego aplikacja wymaga użycia lokalizacji użytkownika. Na przykład „Wyświetla użytkownik, który chce udostępnić wizytówki firm w pobliżu”.

Wdrażanie grupowania znaczników

Wdrażanie grupowania znaczników obejmuje 3 kroki:

  1. Utwórz instancję menedżera klastra.
  2. Przekaż znaczniki, które chcesz pogrupować, do menedżera klastrów.
  3. Wywołaj menedżera klastra.
Aby zobaczyć pełny przykład implementowania grupowania znaczników, zapoznaj się z przykładowymi aplikacjami na GitHubie w językach Objective-C i Swift.

Tworzę menedżera klastra

Aby użyć menedżera klastrów, wykonaj te czynności:

  1. Ustaw ViewController, w którym jest renderowana mapa, tak aby była zgodna z protokołem GMSMapViewDelegate.
  2. Utwórz instancję GMUClusterManager.
  3. Przekaż do instancji GMUClusterManager instancję GMSMapView, w której chcesz wdrożyć klastry znaczników, oraz implementacje tych protokołów:
    • GMUClusterIconGenerator: udostępnia logikę aplikacji, która pobiera ikony klastra, które mają być używane przy różnych poziomach powiększenia.
    • GMUClusterAlgorithm: określa algorytm określający sposób grupowania znaczników, np. odległość między znacznikami do uwzględnienia w tej samej grupie.
    • GMUClusterRenderer: udostępnia logikę aplikacji, która automatycznie renderuje ikony klastrów na mapie.
  4. Ustaw delegata map w instancji GMUClusterManager.

Biblioteka narzędziowa zawiera domyślne implementacje generatora ikon (GMUDefaultClusterIconGenerator), algorytmu (GMUNonHierarchicalDistanceBasedAlgorithm) i mechanizmu renderowania (GMUDefaultClusterRenderer). Opcjonalnie możesz utworzyć własny mechanizm generowania ikon klastra, algorytm i mechanizm renderowania.

Ten kod tworzy menedżera klastra z użyciem tych wartości domyślnych w wywołaniu zwrotnym viewDidLoad 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
      

Dodawanie znaczników

Istnieją 2 sposoby dodawania znaczników do klastra znaczników: pojedynczo lub w postaci tablicy.

Pojedynczy znacznik

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

Tablica znaczników

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

Wywołuję klaster znaczników

Gdy utworzysz klaster znaczników i przekażesz mu znaczniki, które chcesz pogrupować, wystarczy, że wywołasz metodę cluster w instancji klastra znaczników.

Swift

clusterManager.cluster()
      

Objective-C

[_clusterManager cluster];
      

Obsługa zdarzeń w znacznikach i klastrach

Ogólnie, aby nasłuchiwać zdarzeń na mapie, używając pakietu SDK Map Google na iOS, musisz wdrożyć protokół GMSMapViewDelegate. Możesz nasłuchiwać zdarzeń mapowania, ale nie możesz nasłuchiwać zdarzeń menedżera klastra bezpiecznego dla typu. Gdy użytkownik kliknie znacznik, pojedynczy element klastra lub klaster, interfejs API aktywuje mapView:didTapMarker: i dołączy dodatkowe dane klastra do właściwości marker.userData. Następnie możesz sprawdzić, czy userData jest zgodny z protokołem GMUCluster, aby określić, czy kliknięto ikonę klastra lub znacznik.

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

Menedżer klastrów przechwytuje teraz wszystkie zdarzenia zaimplementowane w clusterManager. Przekazuje wszystkie pozostałe zdarzenia do delegata mapowania, jeśli został podany. Pamiętaj, że zdarzenia związane ze znacznikami standardowymi (czyli znaczniki, które nie zostały wygenerowane przez mechanizm renderowania klastra) są zawsze przekierowywane do delegata mapy.

Dostosuj grupowanie znaczników

Możesz podać niestandardową implementację dla właściwości GMUClusterRenderer, GMUClusterIconGenerator lub GMUClusterAlgorithm. Własną implementację możesz oprzeć na przykładowej implementacji tych protokołów w bibliotece narzędzi lub na kodowaniu w pełni niestandardowej implementacji, wypełniając wybrane protokoły.