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;

}


項目中的聚合效果圖: