אשכול סימון

בחירת פלטפורמה: Android iOS JavaScript

בדף הזה מתואר הכלי לאשכולות סמנים שזמין בספריית הכלים ל-SDK של מפות Google ל-iOS.

קיבוץ הסמנים יאפשר לך להוסיף הרבה סמנים למפה בלי להקשות על הקריאה של המפה. הכלי לקיבוץ סמנים עוזר לך לנהל סמנים מרובים ברמות שונות של מרחק מתצוגה.

כשמשתמש מציג את המפה ברמת זום גבוהה, הסמנים השונים מופיעים במפה. כשמשתמש מקטין את התצוגה, הסמנים מקובצים יחד לאשכולות, כדי שיהיה קל יותר לצפות במפה.

צילום המסך הבא מציג את סגנון ברירת המחדל של מקבצי סמנים:

מפה עם סמנים בסגנון ברירת המחדל

בהמשך מוצגת דוגמה לאשכולות סמנים מותאמים אישית:

מפה עם סמנים מקובצים בהתאמה אישית

דרישות מוקדמות והערות

SDK של מפות Google לספריית הכלים של iOS

הכלי לקיבוץ סמנים הוא חלק מה-SDK של מפות Google לספריית הכלים של iOS. אם עדיין לא הגדרת את הספרייה, היעזר במדריך ההגדרה לפני שתקרא את שאר הדף הזה.

לקבלת הביצועים הטובים ביותר, המספר המקסימלי המומלץ של סמנים הוא 10,000.

הרשאת מיקום

בדוגמה הזו נעשה שימוש ב-GPS של המכשיר כדי לאתר את המשתמש ואת המפה בקואורדינטות שלו. כדי להפעיל את האפשרות הזאת, צריך להוסיף תיאור להרשאה NSLocationWhenInUseUsageDescription בקובץ Info.plist של הפרויקט.

כדי להוסיף את המזהה, מבצעים את הפעולות הבאות:

  1. לוחצים על הקובץ Info.plist ב-Project Navigator ב-Xcode כדי לפתוח את העורך של רשימת הנכסים.
  2. כדי להוסיף נכס חדש, לוחצים על הסמל '+' לצד 'רשימת נכסי מידע'.
  3. בשדה 'key', מקלידים 'NSLocationWhenInUseUsageDescription'. מערכת Xcode תתרגם באופן אוטומטי את השם הזה לשם הארוך 'פרטיות – מיקום בעת שימוש בתיאור השימוש'. רשימה מלאה של המאפיינים האפשריים של הרשאות המיקום זמינה במאמר בקשת הרשאה לשירותי מיקום במסמכי התיעוד של Apple למפתחים.
  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 של הקריאה החוזרת (callback) של 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
      

הוספת סמנים

יש שתי דרכים להוסיף סמנים למקבץ הסמנים: בנפרד או כמערך.

סמן אישי

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

מערך סמנים

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

הפעלה של מקבץ הסמנים

לאחר שיצרת את אוסף הסמנים והעברת אותו לסמנים שברצונך לקבץ, כל שעליך לעשות הוא להפעיל את השיטה cluster במופע של אוסף הסמנים.

Swift

clusterManager.cluster()
      

Objective-C

[_clusterManager cluster];
      

טיפול באירועים בסמנים ובאשכולות

באופן כללי, כשמשתמשים ב-SDK של מפות Google ל-iOS, כדי להאזין לאירועים במפה צריך להטמיע את הפרוטוקול GMSMapViewDelegate. אפשר להאזין לאירועי מפה, אבל אי אפשר להאזין לאירועים של מנהלי האשכולות בטוחים לסוג. כשהמשתמש מקיש על סמן, על פריט של אשכול מסוים או על אשכול, ה-API מפעיל את mapView:didTapMarker: ומצרפים את נתוני האשכול הנוספים לנכס marker.userData. לאחר מכן אפשר לבדוק אם userData תואם לפרוטוקול GMUCluster כדי לקבוע אם בוצעה הקשה על סמל אשכול או על סמן.

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

מנהל האשכולות מיירט עכשיו אירועים שהטמעת ב-clusterManager. כל האירועים שנותרו יועברו לאדם שהענקתם לו גישה למפה, אם הם יסופקו. שימו לב שאירועים של סמנים רגילים (כלומר, סמנים שלא נוצרים על ידי הכלי לעיבוד אשכול) תמיד מועברים למאציל המפה.

התאמה אישית של אשכולות סמנים

אפשר לספק הטמעה מותאמת אישית עבור GMUClusterRenderer, GMUClusterIconGenerator או GMUClusterAlgorithm. אפשר לבסס את ההטמעה המותאמת אישית על סמך דגימה של הפרוטוקולים שכלולים בספריית הכלים, או לתכנת הטמעה בהתאמה אישית מלאה לפי הפרוטוקולים.