问题描述
我们如何在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上执行聚类的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!