//xxx.m 文件#import "BasicMapAnnotation.h"#import "BMKClusterManager.h"/* *点聚合Annotation */@interface ClusterAnnotation : BMKPointAnnotation///所包含annotation个数@property (nonatomic, assign) NSInteger size;@end@implementation ClusterAnnotation@synthesize size = _size;@end/* *点聚合AnnotationView */@interface ClusterAnnotationView : BMKPinAnnotationView { }@property (nonatomic, assign) NSInteger size;@property (nonatomic, strong) UILabel *label;@end@implementation ClusterAnnotationView@synthesize size = _size;@synthesize label = _label;- (id)initWithAnnotation:(id)annotation reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier]; if (self) { [self setBounds:CGRectMake(0.f, 0.f, 55.f, 55.f)]; _label = [[UILabel alloc] initWithFrame:CGRectMake(0.f, 0.f, 22.f, 22.f)]; _label.textColor = [UIColor whiteColor]; _label.font = [UIFont systemFontOfSize:11]; _label.textAlignment = NSTextAlignmentCenter; [self addSubview:_label]; self.alpha = 1; } return self;}- (void)setSize:(NSInteger)size { _size = size; if (_size == 1) { self.label.hidden = YES; self.pinColor = BMKPinAnnotationColorRed; return; } self.label.hidden = NO; if (size > 20) { self.label.backgroundColor = [UIColor redColor]; } else if (size > 10) { self.label.backgroundColor = [UIColor purpleColor]; } else if (size > 5) { self.label.backgroundColor = [UIColor blueColor]; } else { self.label.backgroundColor = [UIColor greenColor]; } _label.text = [NSString stringWithFormat:@"%ld", (long)size];}@end@interface WrapperMainViewController () { IBOutlet BMKMapView* _mapView; BMKClusterManager *_clusterManager;//点聚合管理类 NSInteger _clusterZoom;//聚合级别 NSMutableArray *_clusterCaches;//点聚合缓存标注}@end@implementation WrapperMainViewController- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. //[super.navigationController setNavigationBarHidden:NO animated:FALSE];// [self.navigationController setNavigationBarHidden:YES]; // [self.scrollViewMain addSubview:viewMain]; [self.scrollViewMain setContentSize:CGSizeMake(self.view.bounds.size.width, self.view.bounds.size.height - 106)]; mutableArrayButton = [[NSMutableArray alloc] init]; [self addHeader]; labelCity.text = [[AppDelegate instance].dicCurrentCity valueForKeyPath:@"cname"]; labelCity.textAlignment = NSTextAlignmentCenter; //[btnCity setTitle:[[AppDelegate instance].dicCurrentCity valueForKeyPath:@"cname"] forState:UIControlStateNormal]; [[LocationManagement sharedInstance] startGPS]; [LocationManagement sharedInstance].delegate = self; [super getAPPVersion:NO AppId:@"1"]; UITapGestureRecognizer *click = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(disappear)]; [blackAlpha addGestureRecognizer:click]; blackAlpha.frame = CGRectMake(0, 568, self.view.bounds.size.width, self.view.bounds.size.height); [self.view addSubview:blackAlpha]; weatherTableView.frame = CGRectMake(0, 568, weatherTableView.bounds.size.width, 200); [self.view addSubview:weatherTableView]; if (iPhone4s) { scrollViewMain.contentSize = CGSizeMake(scrollViewMain.contentSize.width, 548); } _clusterCaches = [[NSMutableArray alloc] init]; for (NSInteger i = 3; i < 21; i++) { [_clusterCaches addObject:[NSMutableArray array]]; } //点聚合管理类(初始化) _clusterManager = [[BMKClusterManager alloc] init];}- (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated.}- (void)viewWillAppear:(BOOL)animated{ [_mapView viewWillAppear]; _mapView.delegate = self; // 此处记得不用的时候需要置nil,否则影响内存的释放}- (void)viewWillDisappear:(BOOL)animated{ [_mapView viewWillDisappear]; _mapView.delegate = nil; // 不用时,置nil}//更新聚合状态- (void)updateClusters { _clusterZoom = (NSInteger)_mapView.zoomLevel; @synchronized(_clusterCaches) { __block NSMutableArray *clusters = [_clusterCaches objectAtIndex:(_clusterZoom - 3)]; if (clusters.count > 0) { [_mapView removeAnnotations:_mapView.annotations]; [_mapView addAnnotations:clusters]; } else { dispatch_async(dispatch_get_global_queue(0, 0), ^{ ///获取聚合后的标注 __block NSArray *array = [_clusterManager getClusters:_clusterZoom]; dispatch_async(dispatch_get_main_queue(), ^{ for (int i=0;i<[array count];i++) { BMKCluster *item=array[i]; ClusterAnnotation *annotation = [[ClusterAnnotation alloc] init]; annotation.coordinate = item.coordinate; annotation.size = item.size;// annotation.title = [NSString stringWithFormat:@"我是%ld个", (unsigned long)item.size]; annotation.title = [NSString stringWithFormat:@"%d",i]; ParkEntity *entity = homeEntity.mutableArrayPark[i]; annotation.subtitle = entity.album_thumb; [clusters addObject:annotation]; } [_mapView removeAnnotations:_mapView.annotations]; [_mapView addAnnotations:clusters]; }); }); } }}#pragma mark - BMKMapViewDelegate Override (单个标注)//-(BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id )annotation{// if ([annotation isKindOfClass:[BMKPointAnnotation class]]) {// BMKPinAnnotationView *newAnnotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"myAnnotation"];// newAnnotationView.pinColor = BMKPinAnnotationColorPurple;// newAnnotationView.animatesDrop = YES;// 设置该标注点动画显示// newAnnotationView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:annotation.subtitle]]]; newAnnotationView.image=[UIImage imageNamed:@"地图图标_景点@2x"];// return newAnnotationView;// }//// return nil;//}// 根据anntation生成对应的View- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id )annotation{ //普通annotation NSString *AnnotationViewID = @"ClusterMark"; ClusterAnnotation *cluster = (ClusterAnnotation*)annotation; ClusterAnnotationView *annotationView = [[ClusterAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID]; annotationView.size = cluster.size; annotationView.canShowCallout = NO;//在点击大头针的时候会弹出那个黑框框 annotationView.draggable = NO;//禁止标注在地图上拖动 annotationView.annotation = cluster; annotationView.image=[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:annotation.subtitle]]]; return annotationView; }/** *当点击annotation view弹出的泡泡时,调用此接口 *@param mapView 地图View *@param view 泡泡所属的annotation view */- (void)mapView:(BMKMapView *)mapView annotationViewForBubble:(BMKAnnotationView *)view { if ([view isKindOfClass:[ClusterAnnotationView class]]) { ClusterAnnotation *clusterAnnotation = (ClusterAnnotation*)view.annotation; if (clusterAnnotation.size > 1) { [mapView setCenterCoordinate:view.annotation.coordinate]; [mapView zoomIn]; } }}/** *地图初始化完毕时会调用此接口 *@param mapview 地图View */- (void)mapViewDidFinishLoading:(BMKMapView *)mapView { [self updateClusters];}/** *地图渲染每一帧画面过程中,以及每次需要重绘地图时(例如添加覆盖物)都会调用此接口 *@param mapview 地图View *@param status 此时地图的状态 */- (void)mapView:(BMKMapView *)mapView onDrawMapFrame:(BMKMapStatus *)status { if (_clusterZoom != 0 && _clusterZoom != (NSInteger)mapView.zoomLevel) { [self updateClusters]; }}//标注 单击事件-(void)mapView:(BMKMapView *)mapView didSelectAnnotationView:(BMKAnnotationView *)view { if ([view isKindOfClass:[ClusterAnnotationView class]]) { ClusterAnnotation *clusterAnnotation = (ClusterAnnotation*)view.annotation; if (clusterAnnotation.size > 1) { [mapView setCenterCoordinate:view.annotation.coordinate]; [mapView zoomIn]; }else { ParkEntity *entity = [homeEntity.mutableArrayPark objectAtIndex:[clusterAnnotation.title integerValue]]; if ([entity.is_business isEqualToString:@"0"] == YES) { IntroduceViewController *vc = [[IntroduceViewController alloc] init]; vc.parkEntity = entity; [self.navigationController pushViewController:vc animated:YES]; } else { WrapperViewController *vc = [[WrapperViewController alloc] init]; vc.parkEntity = entity; [self.navigationController pushViewController:vc animated:YES]; } } }}@end
//核心代码//添加单点标注for(int i=0;i<[homeEntity.mutableArrayPark count];i++){ ParkEntity *entity = homeEntity.mutableArrayPark[i]; // 添加一个PointAnnotation (景点标注) BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init]; CLLocationCoordinate2D coor; coor.latitude = [entity.latitude floatValue]; coor.longitude = [entity.longitude floatValue]; annotation.coordinate = coor; annotation.title = entity.title; annotation.subtitle=entity.album_thumb; [_mapView addAnnotation:annotation]; } [_clusterManager clearClusterItems];//清除点聚合元素 //添加多点标注(点聚合)for(int i=0;i<[homeEntity.mutableArrayPark count];i++){ ParkEntity *entity = homeEntity.mutableArrayPark[i]; BMKClusterItem *clusterItem = [[BMKClusterItem alloc] init]; clusterItem.coor = CLLocationCoordinate2DMake([entity.latitude floatValue],[entity.longitude floatValue]); [_clusterManager addClusterItem:clusterItem];}
ps:
1、需要用到 Cluster 中的一些类(BMKClusterAlgorithm、BMKClusterItem、BMKClusterManager、BMKClusterQuadtree)
2、annotationView.image 设置标注图片的时候,缩小地图汇出现图片重叠的问题。
可以通过设置 BMKClusterAlgorithm.m 文件中的 #define MAX_DISTANCE_IN_DP 400 //300dp 来设置点聚合算法的距离
3、[_clusterManager clearClusterItems];//清除点聚合元素
for(int i=0;i<[homeEntity.mutableArrayPark count];i++){
ParkEntity *entity = homeEntity.mutableArrayPark[i];
BMKClusterItem *clusterItem = [[BMKClusterItem alloc] init];
clusterItem.coor = CLLocationCoordinate2DMake([entity.latitude floatValue],[entity.longitude floatValue]);
[_clusterManager addClusterItem:clusterItem];
}
//移动地图
ParkEntity *entity = homeEntity.mutableArrayPark[0];
CLLocation *location = [[CLLocation alloc] initWithLatitude:[entity.latitude doubleValue] longitude:[entity.longitude doubleValue]];
[_mapView setCenterCoordinate:location.coordinate animated:YES];
[self updateClusters];
4、
//删除标注
NSArray* array = [NSArray arrayWithArray:_mapView.annotations];
[_mapView removeAnnotations:array];
//清除地图缓存
[_clusterCaches removeAllObjects];
for (NSInteger i = 3; i < 21; i++) {
[_clusterCaches addObject:[NSMutableArray array]];
}