icon google change iphone annotations mkmapview markerclusterer
https://developer.apple.com/sample-code/wwdc/2017/MapKit-Sample.zip

google - iPhone MKMapView Annotation Clustering



change marker icon google maps swift (9)

¿Has mirado ADClusterMapView? https://github.com/applidium/ADClusterMapView

Hace precisamente esto.

Tengo muchos pines para poner en mi mapa, así que creo que sería una buena idea agrupar esas anotaciones. No estoy muy seguro de cómo lograr esto en el iPhone, pude resolver algo con google maps y algunos ejemplos de javascript. Pero iPhone usa su mkmapview y no tengo idea de cómo agrupar las anotaciones allí.

¿Alguna idea o marco que conozca y sea bueno? Gracias.



Al utilizar el código demo de Apple, es fácil implementar el concepto de agrupación en clústeres en nuestro código. developer.apple.com/library/ios/samplecode/PhotoMap/…

Simplemente podemos usar el siguiente código para el Clustering

Pasos para implementar el clustering

Paso 1: Lo importante es que para la agrupación en clúster usamos dos vistas de mapa (allAnnotationsMapView), Uno es para referencia (allAnnotationsMapView)

@property (nonatomic, strong) MKMapView *allAnnotationsMapView; @property (nonatomic, strong) IBOutlet MKMapView *mapView;

En viewDidLoad

_allAnnotationsMapView = [[MKMapView alloc] initWithFrame:CGRectZero];

Paso 2: Agregue todas las anotaciones al _allAnnotationsMapView, a continuación _photos son la matriz de anotaciones.

[_allAnnotationsMapView addAnnotations:_photos]; [self updateVisibleAnnotations];

Paso 3: agregue los siguientes métodos para agrupar en clústeres, en esta Foto La anotación es la anotación personalizada. Métodos MapViewDelegate

- (void)mapView:(MKMapView *)aMapView regionDidChangeAnimated:(BOOL)animated { [self updateVisibleAnnotations]; } - (void)mapView:(MKMapView *)aMapView didAddAnnotationViews:(NSArray *)views { for (MKAnnotationView *annotationView in views) { if (![annotationView.annotation isKindOfClass:[PhotoAnnotation class]]) { continue; } PhotoAnnotation *annotation = (PhotoAnnotation *)annotationView.annotation; if (annotation.clusterAnnotation != nil) { // animate the annotation from it''s old container''s coordinate, to its actual coordinate CLLocationCoordinate2D actualCoordinate = annotation.coordinate; CLLocationCoordinate2D containerCoordinate = annotation.clusterAnnotation.coordinate; // since it''s displayed on the map, it is no longer contained by another annotation, // (We couldn''t reset this in -updateVisibleAnnotations because we needed the reference to it here // to get the containerCoordinate) annotation.clusterAnnotation = nil; annotation.coordinate = containerCoordinate; [UIView animateWithDuration:0.3 animations:^{ annotation.coordinate = actualCoordinate; }]; } } }

Métodos de manejo de clustering

- (id<MKAnnotation>)annotationInGrid:(MKMapRect)gridMapRect usingAnnotations:(NSSet *)annotations { // first, see if one of the annotations we were already showing is in this mapRect NSSet *visibleAnnotationsInBucket = [self.mapView annotationsInMapRect:gridMapRect]; NSSet *annotationsForGridSet = [annotations objectsPassingTest:^BOOL(id obj, BOOL *stop) { BOOL returnValue = ([visibleAnnotationsInBucket containsObject:obj]); if (returnValue) { *stop = YES; } return returnValue; }]; if (annotationsForGridSet.count != 0) { return [annotationsForGridSet anyObject]; } // otherwise, sort the annotations based on their distance from the center of the grid square, // then choose the one closest to the center to show MKMapPoint centerMapPoint = MKMapPointMake(MKMapRectGetMidX(gridMapRect), MKMapRectGetMidY(gridMapRect)); NSArray *sortedAnnotations = [[annotations allObjects] sortedArrayUsingComparator:^(id obj1, id obj2) { MKMapPoint mapPoint1 = MKMapPointForCoordinate(((id<MKAnnotation>)obj1).coordinate); MKMapPoint mapPoint2 = MKMapPointForCoordinate(((id<MKAnnotation>)obj2).coordinate); CLLocationDistance distance1 = MKMetersBetweenMapPoints(mapPoint1, centerMapPoint); CLLocationDistance distance2 = MKMetersBetweenMapPoints(mapPoint2, centerMapPoint); if (distance1 < distance2) { return NSOrderedAscending; } else if (distance1 > distance2) { return NSOrderedDescending; } return NSOrderedSame; }]; PhotoAnnotation *photoAnn = sortedAnnotations[0]; NSLog(@"lat long %f %f", photoAnn.coordinate.latitude, photoAnn.coordinate.longitude); return sortedAnnotations[0]; } - (void)updateVisibleAnnotations { // This value to controls the number of off screen annotations are displayed. // A bigger number means more annotations, less chance of seeing annotation views pop in but decreased performance. // A smaller number means fewer annotations, more chance of seeing annotation views pop in but better performance. static float marginFactor = 2.0; // Adjust this roughly based on the dimensions of your annotations views. // Bigger numbers more aggressively coalesce annotations (fewer annotations displayed but better performance). // Numbers too small result in overlapping annotations views and too many annotations on screen. static float bucketSize = 60.0; // find all the annotations in the visible area + a wide margin to avoid popping annotation views in and out while panning the map. MKMapRect visibleMapRect = [self.mapView visibleMapRect]; MKMapRect adjustedVisibleMapRect = MKMapRectInset(visibleMapRect, -marginFactor * visibleMapRect.size.width, -marginFactor * visibleMapRect.size.height); // determine how wide each bucket will be, as a MKMapRect square CLLocationCoordinate2D leftCoordinate = [self.mapView convertPoint:CGPointZero toCoordinateFromView:self.view]; CLLocationCoordinate2D rightCoordinate = [self.mapView convertPoint:CGPointMake(bucketSize, 0) toCoordinateFromView:self.view]; double gridSize = MKMapPointForCoordinate(rightCoordinate).x - MKMapPointForCoordinate(leftCoordinate).x; MKMapRect gridMapRect = MKMapRectMake(0, 0, gridSize, gridSize); // condense annotations, with a padding of two squares, around the visibleMapRect double startX = floor(MKMapRectGetMinX(adjustedVisibleMapRect) / gridSize) * gridSize; double startY = floor(MKMapRectGetMinY(adjustedVisibleMapRect) / gridSize) * gridSize; double endX = floor(MKMapRectGetMaxX(adjustedVisibleMapRect) / gridSize) * gridSize; double endY = floor(MKMapRectGetMaxY(adjustedVisibleMapRect) / gridSize) * gridSize; // for each square in our grid, pick one annotation to show gridMapRect.origin.y = startY; while (MKMapRectGetMinY(gridMapRect) <= endY) { gridMapRect.origin.x = startX; while (MKMapRectGetMinX(gridMapRect) <= endX) { NSSet *allAnnotationsInBucket = [self.allAnnotationsMapView annotationsInMapRect:gridMapRect]; NSSet *visibleAnnotationsInBucket = [self.mapView annotationsInMapRect:gridMapRect]; // we only care about PhotoAnnotations NSMutableSet *filteredAnnotationsInBucket = [[allAnnotationsInBucket objectsPassingTest:^BOOL(id obj, BOOL *stop) { return ([obj isKindOfClass:[PhotoAnnotation class]]); }] mutableCopy]; if (filteredAnnotationsInBucket.count > 0) { PhotoAnnotation *annotationForGrid = (PhotoAnnotation *)[self annotationInGrid:gridMapRect usingAnnotations:filteredAnnotationsInBucket]; [filteredAnnotationsInBucket removeObject:annotationForGrid]; // give the annotationForGrid a reference to all the annotations it will represent annotationForGrid.containedAnnotations = [filteredAnnotationsInBucket allObjects]; [self.mapView addAnnotation:annotationForGrid]; for (PhotoAnnotation *annotation in filteredAnnotationsInBucket) { // give all the other annotations a reference to the one which is representing them annotation.clusterAnnotation = annotationForGrid; annotation.containedAnnotations = nil; // remove annotations which we''ve decided to cluster if ([visibleAnnotationsInBucket containsObject:annotation]) { CLLocationCoordinate2D actualCoordinate = annotation.coordinate; [UIView animateWithDuration:0.3 animations:^{ annotation.coordinate = annotation.clusterAnnotation.coordinate; } completion:^(BOOL finished) { annotation.coordinate = actualCoordinate; [self.mapView removeAnnotation:annotation]; }]; } } } gridMapRect.origin.x += gridSize; } gridMapRect.origin.y += gridSize; } }

Siguiendo los pasos anteriores podemos lograr la agrupación en clusterview, no es necesario utilizar ningún código o marco de terceros. Por favor verifique el developer.apple.com/library/ios/samplecode/PhotoMap/… aquí. Por favor, hágamelo saber si tiene alguna duda al respecto.


Dado que este es un problema muy común y necesitaba una solución, escribí una subclase personalizada de MKMapView que admite la agrupación en clústeres. Entonces lo hice disponible de código abierto! Puede obtenerlo aquí: https://github.com/yinkou/OCMapView .

Administra el agrupamiento de las anotaciones y usted puede manejar sus vistas por sí mismo. No tiene que hacer nada más que copiar la carpeta OCMapView a su proyecto, crear un MKMapView en su plumilla y establecer su clase en OCMapView . (O cree y delegue en código como un MKMapView normal)


Hay una biblioteca bastante buena y bien mantenida para Objective-C y Swift aquí: https://github.com/bigfish24/ABFRealmMapView

Lo hace realmente bien agrupando y también maneja grandes cantidades de puntos debido a su integración con Realm .


No necesariamente tiene que usar un marco de terceros porque desde iOS 4.2, MKMapView tiene un método llamado - (NSSet *)annotationsInMapRect:(MKMapRect)mapRect que puede usar para hacer su agrupamiento.

Vea el video de la sesión WWDC11 '' Visualización de información geográfica con MapKit ''. A mitad de camino explica cómo hacerlo. Pero voy a resumir el concepto para usted:

  • Utilice Dos mapas (el segundo mapa nunca se agrega a la jerarquía de vista )
  • El segundo mapa contiene todas las anotaciones (de nuevo, nunca se dibuja )
  • Divide el área del mapa en una cuadrícula de cuadrados
  • Utilice el método -annotationsInMapRect para obtener datos de anotación de un mapa invisible
  • El mapa visible construye sus anotaciones a partir de estos datos del mapa invisible.

Pruebe este marco (XMapView.framework); ahora es compatible con iOS 8.

Este marco no necesita que cambie la estructura actual de su proyecto y se puede utilizar directamente para su MKMapView. Hay un archivo zip. Te da un ejemplo para agrupar 200 pines a la vez. Después de probarlo en un iPod, encontré que es muy suave.

http://www.xuliu.info/xMapView.html

Esta biblioteca soporta:

  1. agrupando diferentes categorías
  2. agrupando todas las categorías
  3. configurando su propio radio de grupo y así sucesivamente
  4. esconder o mostrar algunas categorías
  5. Manejar y controlar individualmente cada pin en el mapa.

Recientemente descarté de ADClusterMapView mencionado en otra respuesta y resolví muchos, si no todos, los problemas asociados con el proyecto. Es un algoritmo kd-tree y anima el agrupamiento.

Está disponible el código abierto aquí https://github.com/ashare80/TSClusterMapView