iOS-百度地图聚合

百度地图的应用也是极为广泛,从基本的定位,大头针的展现到线路的规划等等,但如果地图页面上在某一个区域内展示的大头针过多的话会在地图上面一团一团的都是满满的大头针,或许我们将地图缩小到某个区域之后用户并不关心某一个具体的大头针了,而成团的大头针叠在一起给人的感觉很不好,百度地图 SDK 在 2.9 的版本以后新增了 

BMKClusterManager 的这样一个点聚合管理类.原理很简单,就是当地图缩放到某个级别的时候让地图显示另外一个类型的大头针.


百度地图聚合功能的实现:

{

    BMKClusterManager *_clusterManager;//点聚合管理类

    NSInteger _clusterZoom;//聚合级别

    CGFloat _clusterFloatZoom;//百度地图聚合的浮点数级别

    NSMutableArray *_clusterCaches;//点聚合缓存标注

    NSInteger _previousZoom; // 记录前一次的缩放等级

}


#pragma mark - 更新聚合状态

//更新聚合状态

- (void)updateClusters {

    _clusterZoom = (NSInteger)_mapView.zoomLevel;

    _clusterFloatZoom=_mapView.zoomLevel;

    

//    NSLog(@"当前更新地图的时候地图的缩放级别为: %f",_mapView.zoomLevel);

//    NSLog(@"当前更新地图时地图的缩放级别取整结果: %ld",_clusterZoom);

    //NSLog(@"--现在当前的地图缩放级别为 %d",_clusterZoom);

    if (_clusterZoom<11) { // 目前是当地图缩放级别小于 11 级的时候才开始聚合

        if (_dataSource.count < 150) {

            return;

        }

       [self getStationModelToJuHeAnnotation];

        @synchronized(_clusterCaches) {

            __block NSMutableArray *clusters = [_clusterCaches objectAtIndex:(_clusterZoom -3)];

            

            if (clusters.count > 0) {

                [_mapView removeAnnotations:_mapView.annotations];

                [_mapView addAnnotations:clusters];

                [_mapView addAnnotation:_selfLocalModel];

            } else {

                dispatch_async(dispatch_get_global_queue(00), ^{

                    ///获取聚合后的标注

                    __block NSArray *array = [_clusterManager getClusters:_clusterFloatZoom];

                    dispatch_async(dispatch_get_main_queue(), ^{

                        for (BMKCluster *item in array) {

                            // 获得每一个聚合之后标注的内容(个数,经纬度)

                            ClusterAnnotation *annotation = [[ClusterAnnotation allocinit];

                            annotation.coordinate = item.coordinate;

                            annotation.size = item.size;

                            annotation.title = [NSString stringWithFormat:@"我是%ld", item.size];

                            [clusters addObject:annotation];

                            

                            int yellow=0;

                            int blue=0;

                            int gray=0;

                            

                            for (JuHeModel* model in item.clusterItems) {

                                if ([model.categary intValue] ==3) {

                                    yellow++;

                                }else if ([model.categary intValue] == 2){

                                    blue++;

                                }else if([model.categary intValue] ==1){

                                    gray++;

                                }

                            }

                            annotation.yellowCount=[NSString stringWithFormat:@"%d",yellow];

                            annotation.blewCount=[NSString stringWithFormat:@"%d",blue];

                            annotation.grayCount=[NSString stringWithFormat:@"%d",gray];

                        }

                        [_mapView removeAnnotations:_mapView.annotations];

                        [_mapView addAnnotations:clusters];

                        [_mapView addAnnotation:_selfLocalModel];

                    });

                });

            }

        }

        

    }else{

        if (_previousZoom!= (NSInteger)_mapView.zoomLevel ) {

            

            [_mapView removeAnnotations:_mapView.annotations];

            [_mapView addAnnotations:_dataSource];

            [_mapView addAnnotation:_selfLocalModel];

        }

    }

    // 记录前一次的缩放比例

    _previousZoom=(NSInteger)_mapView.zoomLevel;

    

}


/** _dataSource 为从服务器获取的数据模型数组*/

-(void)getStationModelToJuHeAnnotation

{

    [self addJuHecoordinate:_dataSource];

}

-(void)addJuHecoordinate:(NSArray*)models

{

    //点聚合管理类

    _clusterManager = [[BMKClusterManager allocinit];

    for (LocalModel* model in models) {

        JuHeModel* clusterItem=[[JuHeModel allocinit];

        clusterItem.coor=model.coordinate;

        clusterItem.categary=model.category;

        [_clusterManager addClusterItem:clusterItem];

    }

}




#program mark -- 百度地图代理方法

- (void)mapView:(BMKMapView *)mapView regionDidChangeAnimated:(BOOL)animated

{

    NSLog(@"地图代理中区域发生变化时当前地图的所缩放级别:%f",mapView.zoomLevel);

    if (_previousZoom != (NSInteger)mapView.zoomLevel) {

        [self updateClusters];

    }

}


// 根据anntation生成对应的View

/**

  ClusterAnnotation     遵从BMKAnnotation 协议的大头针模型   

  ClusterAnnotationView  为自定义的聚合模型,目前展示的是外面一圈色带展示所聚合区域类不同类型的占比

*/

- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id<BMKAnnotation>)annotation

{

    [self hideHud];

    //普通annotation

    if ([annotation isKindOfClass:[ClusterAnnotation class]]) {  // 聚合类

        NSString *AnnotationViewID = @"ClusterMark";

        ClusterAnnotation *cluster = (ClusterAnnotation*)annotation;

        ClusterAnnotationView *annotationView = [[ClusterAnnotationView allocinitWithAnnotation:annotation reuseIdentifier:AnnotationViewID];

        annotationView.size = cluster.size;

        // 按返回比例计算

//        annotationView.bluScal=[cluster.blewCount intValue] * 1.0 / (cluster.size * 1.0);

//        annotationView.yellowScal=[cluster.yellowCount intValue] * 1.0 / (cluster.size * 1.0);

//        annotationView.grayScal=[cluster.grayCount intValue] * 1.0 / (cluster.size * 1.0);

        

        // 周围只选择蓝色一圈

        annotationView.bluScal=1.0;

        

        // NSLog(@"%d--%d     %f  %f  %f",cluster.size,cluster.size-2, annotationView.bluScal,annotationView.yellowScal,annotationView.grayScal);

        annotationView.draggable = YES;

        //annotationView.canShowCallout=NO;

        annotationView.annotation = cluster;

        return annotationView;

    }else if ([annotation isKindOfClass:[LocalModel class]]) { // 非聚合类


        /** 根据数据模型 想展示怎样的大头针自己定义*/


        return newAnnotationView;

    }

    return nil;

}


项目中的聚合效果图: