Klasteryzacja znaczników

Wybierz platformę: Android iOS JavaScript

Na tej stronie znajdziesz opis narzędzia do łączenia znaczników w klastry, które jest dostępne w bibliotece narzędzi pakietu Maps SDK na iOS.

Dzięki łączeniu znaczników w klastry możesz umieścić na mapie dużą liczbę znaczników bez utrudniania jej czytelności. Narzędzie do łączenia znaczników w klastry pomaga zarządzać wieloma znacznikami na różnych poziomach powiększenia.

Gdy użytkownik wyświetla mapę na wysokim poziomie powiększenia, na mapie widoczne są poszczególne znaczniki. Gdy użytkownik oddala widok, znaczniki łączą się w klastry, co ułatwia przeglądanie mapy.

Poniższy zrzut ekranu przedstawia domyślny styl klastrów znaczników:

Mapa z pogrupowanymi znacznikami w stylu domyślnym

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

Mapa z niestandardowymi zgrupowanymi znacznikami

Wymagania wstępne i uwagi

Biblioteka narzędzi pakietu Maps SDK na iOS

Narzędzie do łączenia znaczników w klastry jest częścią biblioteki narzędzi pakietu Maps SDK na iOS. Jeśli nie masz jeszcze skonfigurowanej biblioteki, przed przeczytaniem reszty tej strony zapoznaj się z przewodnikiem konfiguracji.

Aby uzyskać najlepsze wyniki, zalecamy używanie maksymalnie 10 tys. znaczników.

Dostęp do lokalizacji

W tym przykładzie używamy GPS urządzenia do lokalizowania użytkownika i mapy na podstawie jego współrzędnych. Aby włączyć to, musisz dodać opis do uprawnienia NSLocationWhenInUseUsageDescription w pliku Info.plist projektu.

Aby to zrobić:

  1. W Xcode kliknij plik Info.plist w nawigatorze projektu, aby otworzyć edytor listy właściwości.
  2. Kliknij ikonę „+” obok opcji „Information Property List” (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ść – opis użycia lokalizacji, gdy aplikacja jest używana). Pełną listę możliwych właściwości dostępu do lokalizacji znajdziesz w dokumentacji Apple Developer w artykule Requesting Authorization for Location Services (Prośba o autoryzację usług lokalizacyjnych).
  4. W polu „Type” (Typ) pozostaw ustawienie „String” (Ciąg znaków).
  5. W polu „Value” (Wartość) wpisz opis powodu, dla którego Twoja aplikacja wymaga dostępu do lokalizacji użytkownika. Na przykład „Lokalizuje użytkownika, aby wyświetlać informacje o firmach w pobliżu”.

Wdrażanie łączenia znaczników w klastry

Wdrażanie łączenia znaczników w klastry wymaga 3 kroków:

  1. Utwórz instancję menedżera klastrów.
  2. Przekaż do menedżera klastrów znaczniki, które chcesz połączyć w klastry.
  3. Wywołaj menedżera klastrów.
Aby zobaczyć pełny przykład wdrażania łączenia znaczników w klastry, zapoznaj się z przykładowymi aplikacjami w językach Objective-C i Swift w GitHubie.

Tworzenie menedżera klastrów

Aby użyć menedżera klastrów:

  1. Ustaw ViewController, w którym renderowana jest mapa, tak aby był zgodny z GMSMapViewDelegate protokołem.
  2. Utwórz instancję GMUClusterManager.
  3. Przekaż do instancji GMUClusterManager instancję GMSMapView, w której chcesz wdrożyć łączenie znaczników w klastry , oraz implementacje tych protokołów:
    • GMUClusterIconGenerator: udostępnia logikę aplikacji, która pobiera ikony klastrów do użycia na różnych poziomach powiększenia.
    • GMUClusterAlgorithm: określa algorytm, który decyduje o sposobie łączenia znaczników w klastry , np. o odległości między znacznikami, które mają być uwzględnione w tym samym klastrze.
    • GMUClusterRenderer: udostępnia logikę aplikacji, która obsługuje rzeczywiste renderowanie ikon klastrów na mapie.
  4. Ustaw delegata mapy w instancji GMUClusterManager.

Biblioteka narzędzi zawiera domyślne implementacje generatora ikon (GMUDefaultClusterIconGenerator), algorytmu (GMUNonHierarchicalDistanceBasedAlgorithm) i renderera (GMUDefaultClusterRenderer). Możesz też utworzyć własny niestandardowy generator ikon, algorytm i renderer.

Poniższy kod tworzy menedżera klastrów, który używa tych domyślnych ustawień w viewDidLoad wywołaniu zwrotnym 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

Znaczniki można dodawać do rozwiązania do łączenia znaczników w klastry na 2 sposoby: pojedynczo lub jako tablicę.

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ływanie narzędzia do łączenia znaczników w klastry

Gdy utworzysz rozwiązanie do łączenia znaczników w klastry i przekażesz do niego znaczniki, które chcesz połączyć w klastry, wszystko co musisz zrobić, to wywołać metodę cluster w instancji rozwiązania do łączenia znaczników w klastry.

Swift

clusterManager.cluster()
      

Objective-C

[_clusterManager cluster];
      

Obsługa zdarzeń dotyczących znaczników i klastrów

Ogólnie rzecz biorąc, aby nasłuchiwać zdarzeń na mapie podczas korzystania z pakietu Maps SDK na iOS, musisz zaimplementować protokół GMSMapViewDelegate. Możesz nasłuchiwać zdarzeń na mapie, ale nie możesz nasłuchiwać zdarzeń menedżera klastrów, które są bezpieczne pod względem typów. Gdy użytkownik kliknie znacznik, pojedynczy element klastra lub klaster, interfejs API wywoła mapView:didTapMarker: i dołączy dodatkowe dane klastra do właściwości marker.userData. Następnie możesz sprawdzić, czy userData jest zgodna z protokołem GMUCluster, aby określić, czy kliknięto ikonę klastra czy 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, które zostały zaimplementowane w clusterManager. Wszystkie pozostałe zdarzenia przekazuje do delegata mapy, jeśli jest on dostępny. Pamiętaj, że zdarzenia dotyczące standardowych znaczników (czyli znaczników, które nie zostały wygenerowane przez mechanizm renderowania klastrów) są zawsze przekazywane do delegata mapy.

Dostosowywanie łączenia znaczników w klastry

Możesz podać niestandardową implementację dla GMUClusterRenderer, GMUClusterIconGenerator, lub GMUClusterAlgorithm. Możesz oprzeć swoją niestandardową implementację na przykładowej implementacji tych protokołów zawartej w bibliotece narzędzi lub napisać w pełni niestandardową implementację, która spełnia wymagania protokołów.