如何在iOS中的Google Map上执行聚类 [英] How to perform clustering on google map in iOS
问题描述
我们如何在iOS的Google地图上使用GMS标记的聚类.如果有人有代码,请先分享.谢谢
How we can use clustering of GMS marker on google map in iOS.if anyone have code then please share.Thank you in advance
推荐答案
子类化UIMapView.CAClusterAnnotation-集群.CACatchAnnotation-单数.
Subclass a UIMapView. CAClusterAnnotation - clustered. CACatchAnnotation - singular.
.h
#import <MapKit/MapKit.h>
@interface CAMapView : MKMapView <MKMapViewDelegate>
@property (nonatomic) BOOL shouldCluster;
- (void)performClustering;
@end
.m
#import "CAMapView.h"
#import "CASpotClusterAnnotation.h"
#import "CACatchClusterAnnotation.h"
#include <math.h>
@interface CAMapView ()
@property (nonatomic) MKCoordinateSpan previousSpan;
@property (nonatomic) NSInteger previousCount;
@property (strong, nonatomic) NSMutableArray *allAnnotations;
@end
@implementation CAMapView
#pragma mark - Annotations
- (void)addAnnotation:(id<MKAnnotation>)annotation {
[_allAnnotations addObject:annotation];
[self performClustering];
}
- (void)removeAnnotation:(id<MKAnnotation>)annotation {
[_allAnnotations removeObject:annotation];
[self performClustering];
}
- (void)addAnnotations:(NSArray *)annotations {
[_allAnnotations setArray:annotations];
[self performClustering];
}
- (void)removeAnnotations:(NSArray *)annotations {
[_allAnnotations removeAllObjects];
[self performClustering];
}
- (CLLocationDistance)currentVisibleMapDistance {
MKMapRect mRect = self.visibleMapRect;
MKMapPoint eastMapPoint = MKMapPointMake(MKMapRectGetMinX(mRect), MKMapRectGetMidY(mRect));
MKMapPoint westMapPoint = MKMapPointMake(MKMapRectGetMaxX(mRect), MKMapRectGetMidY(mRect));
return MKMetersBetweenMapPoints(eastMapPoint, westMapPoint);
}
- (NSArray *)clustersWithAnnotations:(NSArray *)annotations {
NSMutableArray *resultArray = [@[] mutableCopy];
NSMutableArray *usedAnnotations = [@[] mutableCopy];
BOOL hasIntersections = NO;
for (id<MKAnnotation> annotation in annotations) {
if ([usedAnnotations containsObject:annotation]) continue;
[usedAnnotations addObject:annotation];
NSMutableArray *clusterAnnotations = nil;
CGRect activeRect = CGRectZero;
CGPoint annotationPoint = [self convertCoordinate:annotation.coordinate
toPointToView:self];
if (![annotation isKindOfClass:[CAClusterAnnotation class]]) {
clusterAnnotations = [NSMutableArray arrayWithArray:@[annotation]];
activeRect = CGRectMake(annotationPoint.x,
annotationPoint.y,
20.0f,
20.0f);
}
else {
CGSize size = [[CAClusterAnnotation fontAndSizeWithAnnotationsCount:[(CAClusterAnnotation *)annotation annotations].count][@"size"] CGSizeValue];
activeRect = CGRectMake(annotationPoint.x,
annotationPoint.y,
size.width,
size.height);
}
for (id<MKAnnotation> anAnnotation in annotations) {
if ([usedAnnotations containsObject:anAnnotation]) continue;
CGPoint point = [self convertCoordinate:anAnnotation.coordinate
toPointToView:self];
CGRect rect = CGRectZero;
if ([anAnnotation isKindOfClass:[CAClusterAnnotation class]]) {
CGSize size = [[CAClusterAnnotation fontAndSizeWithAnnotationsCount:[(CAClusterAnnotation *)anAnnotation annotations].count][@"size"] CGSizeValue];
rect = CGRectMake(point.x,
point.y,
size.width,
size.height);
}
else {
rect = CGRectMake(point.x,
point.y,
20.0f,
20.0f);
}
if (CGRectIntersectsRect(activeRect, rect)) {
hasIntersections = YES;
[usedAnnotations addObject:anAnnotation];
if ([annotation isKindOfClass:[CAClusterAnnotation class]]) {
if ([anAnnotation isKindOfClass:[CAClusterAnnotation class]]) {
[((CAClusterAnnotation *)annotation).annotations addObjectsFromArray:[(CAClusterAnnotation *)anAnnotation annotations]];
}
else {
[((CAClusterAnnotation *)annotation).annotations addObject:anAnnotation];
}
}
else {
if ([anAnnotation isKindOfClass:[CAClusterAnnotation class]]) {
[clusterAnnotations addObjectsFromArray:[(CAClusterAnnotation *)anAnnotation annotations]];
}
else {
[clusterAnnotations addObject:anAnnotation];
}
}
}
}
if (clusterAnnotations) {
if (clusterAnnotations.count == 1) {
[resultArray addObject:[clusterAnnotations lastObject]];
}
else {
if ([[annotations lastObject] isKindOfClass:[CACatch class]]) {
CACatchClusterAnnotation *clusterAnnotation = [CACatchClusterAnnotation new];
clusterAnnotation.annotations = clusterAnnotations;
[resultArray addObject:clusterAnnotation];
}
else {
CASpotClusterAnnotation *clusterAnnotation = [CASpotClusterAnnotation new];
clusterAnnotation.annotations = clusterAnnotations;
[resultArray addObject:clusterAnnotation];
}
}
}
else {
[resultArray addObject:annotation];
}
}
if (!hasIntersections)
return resultArray;
else
return [self clustersWithAnnotations:resultArray];
}
- (void)performClustering {
for (id<MKAnnotation> annotation in self.annotations) {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
_locationBtn.selected = (fabs([annotation coordinate].latitude - self.centerCoordinate.latitude) < .0001f
&& fabs([annotation coordinate].longitude - self.centerCoordinate.longitude) < .0001f);
break;
}
}
if (fabs(_previousSpan.latitudeDelta) > .0001f
&& fabs(_previousSpan.longitudeDelta) > .0001f) {
if (fabs(self.region.span.longitudeDelta - _previousSpan.longitudeDelta) < .00001f) {
self.previousSpan = self.region.span;
if (_previousCount && _allAnnotations.count) {
return;
}
}
}
for (id<MKAnnotation> annotation in self.selectedAnnotations) {
[self deselectAnnotation:annotation animated:NO];
}
self.previousSpan = self.region.span;
self.previousCount = _allAnnotations.count;
for (id<MKAnnotation> annotation in self.annotations) {
if ([annotation isKindOfClass:[MKUserLocation class]]) continue;
[super removeAnnotation:annotation];
}
if (!_shouldCluster) {
if (_allAnnotations.count) {
[super addAnnotations:_allAnnotations];
}
return;
}
if (!_allAnnotations.count) return;
NSMutableArray *buffer = [@[] mutableCopy];
[buffer addObjectsFromArray:[self clustersWithAnnotations:_allAnnotations]];
[super addAnnotations:buffer];
}
@end
编辑: CACatchClusterAnnotation
和 CASpotClusterAnnotation
都是 CAClusterAnnotation
的子类,您需要使用它们,我用这两个来区分集群注释的类型.情况只有一种.该代码具有很多体系结构上的缺陷,但是我没有时间修复它们,尽管它足以供您使用.
EDIT:
CACatchClusterAnnotation
and CASpotClusterAnnotation
are both subclasses of CAClusterAnnotation
, which you need to use, I used those two to distinguish the type of cluster annotation, in your case it's only one type. The code has a lot of architectural flaws, but I don't have any time to fix them, it should be sufficient for you to work with though.
CAClusterAnnotation.h
CAClusterAnnotation.h
#import <Foundation/Foundation.h>
@interface CAClusterAnnotation : NSObject <MKAnnotation>
// <MKAnnotation> conformation properties
@property (copy, nonatomic) NSString *title;
@property (nonatomic) CLLocationCoordinate2D coordinate;
// Annotations setter that will update |coordinate|
@property (strong, nonatomic) NSMutableArray *annotations;
@end
CAClusterAnnotation.m
CAClusterAnnotation.m
#import "CAClusterAnnotation.h"
@implementation CAClusterAnnotation
- (void)setAnnotations:(NSMutableArray *)annotations {
_annotations = annotations;
MKMapRect r = MKMapRectNull;
for (NSUInteger i=0; i < _annotations.count; ++i) {
MKMapPoint p = MKMapPointForCoordinate([_annotations[i] coordinate]);
r = MKMapRectUnion(r, MKMapRectMake(p.x, p.y, 0, 0));
}
self.coordinate = MKCoordinateRegionForMapRect(r).center;
}
+ (NSDictionary *)fontAndSizeWithAnnotationsCount:(NSInteger)count {
UIFont *font = [UIFont fontWithName:CAFontNameDefaultRegular size:12.0f];
UIImage *img = [UIImage imageNamed:@"spotlist_map_other_spot_icon"];
NSString *catchesNumberStr = (count > 999) ? @"999+" : [NSString stringWithFormat:@"%d", count];
CGSize size = CGSizeMake([catchesNumberStr sizeWithFont:font].width + 6.0f, img.size.height);
size.width = MAX(size.width, img.size.width);
return @{@"font" : font, @"size" : [NSValue valueWithCGSize:size]};
}
@end
在管理 MKMapView
.m文件的视图控制器中,您需要实现至少两种方法-一种呈现注释,另一种在需要时执行聚类:
In the view controller that manages your MKMapView
.m file, you need to implement at least two methods - one to render your annotations, another one to perform clustering whenever it's needed:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *annotationView = nil;
if ([annotation isKindOfClass:[CACatch class]]) {
NSString *catchIdentifier = @"catch";
annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:catchIdentifier];
if (!annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:catchIdentifier];
annotationView.image = [UIImage imageNamed:@"icon"];
}
}
else if ([annotation isKindOfClass:[CAClusterAnnotation class]]) {
static NSString *catchIdentifier = @"catchCluster";
annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:catchIdentifier];
if (!annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:catchIdentifier];
}
NSInteger catchesCount = [(CACatchClusterAnnotation *)annotation annotations].count;
NSDictionary *fontAndSize = [CAClusterAnnotation fontAndSizeWithAnnotationsCount:catchesCount];
UIImage *img = [UIImage imageNamed:@"cluster_icon"];
NSString *catchesNumberStr = (catchesCount > 999) ? @"999+" : [NSString stringWithFormat:@"%d", catchesCount];
CGSize size = [fontAndSize[@"size"] CGSizeValue];
UIImageView *imgView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, MAX(size.width, img.size.width), size.height)];
imgView.backgroundColor = [UIColor clearColor];
imgView.opaque = NO;
imgView.image = [img resizableImageWithCapInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 10.0f)];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, imgView.frame.size.width, imgView.frame.size.height - 2.0f)];
label.backgroundColor = [UIColor clearColor];
label.font = fontAndSize[@"font"];
label.textColor = [UIColor whiteColor];
label.text = catchesNumberStr;
label.textAlignment = NSTextAlignmentCenter;
[imgView addSubview:label];
UIGraphicsBeginImageContextWithOptions(imgView.bounds.size, imgView.opaque, 0.0);
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
annotationView.image = img;
}
else if ([annotation isKindOfClass:[MKUserLocation class]]) {
static NSString *userIdentifier = @"user";
annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:userIdentifier];
if (!annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:userIdentifier];
annotationView.canShowCallout = YES;
}
annotationView.image = [UIImage imageNamed:@"current_location_icon"];
}
return annotationView;
}
- (void)mapView:(CAMapView *)mapView regionDidChangeAnimated:(BOOL)animated {
[mapView performClustering];
}
这篇关于如何在iOS中的Google Map上执行聚类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!