浏览器版本低!无法浏览完整内容,建议升级或更换浏览器。

iOS 地图SDK

百度地图SDK是一套应用程序接口, 通过调用地图SDK接口,开发者可以轻松访问百度地图的服务和数据,构建功能丰富、交互性强的地图类应用程序。

点标记

点标记用来在地图上标记任何位置,例如用户位置、车辆位置、店铺位置等一切带有位置属性的事物。

地图 SDK 提供的点标记功能包含两大部分,一部分是点(俗称Annotation)、另一部分是浮于点上方的信息窗体(俗称 PaopaoView)。同时,SDK对Annotation和paopaoView封装了大量的触发事件,例如点击事件、长按事件、拖拽事件。

Annotation和 PaopaoView 有默认风格,同时也支持自定义。由于内容丰富,以下只能展示一些基础功能的使用,详细内容可分别参考官方参考手册。

添加默认样式标记

BMKAnnotation为标注对应的protocol,您可以自定义标注类实现该protocol。iOS SDK也预置了基本的标注点(BMKPointAnnotation)和一个大头针标注View(BMKPinAnnotationView),您可以直接使用来显示标注。

iOS SDK提供的大头针标注BMKPinAnnotationView,通过它可以设置大头针颜色、是否显示动画等。

在地图上添加大头针标注的步骤如下:

1viewDidAppear方法中添加如下所示代码添加标注数据对象。
BMKPointAnnotation* annotation = [[BMKPointAnnotation alloc]init]; 
annotation.coordinate = CLLocationCoordinate2DMake(39.915, 116.404);
annotation.title = @"这里是北京";    
[_mapView addAnnotation:annotation];   
2实现 <BMKMapViewDelegate> 协议中的 mapView:viewForAnnotation:回调函数,设置标注样式。 如下所示:
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[BMKPointAnnotation class]]) {
        static NSString *pointReuseIndentifier = @"pointReuseIndentifier";
        BMKPinAnnotationView*annotationView = (BMKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:pointReuseIndentifier];
        if (annotationView == nil) {
            annotationView = [[BMKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:pointReuseIndentifier];
        }
        annotationView.pinColor = BMKPinAnnotationColorPurple;
        annotationView.canShowCallout= YES;      //设置气泡可以弹出,默认为NO
        annotationView.animatesDrop=YES;         //设置标注动画显示,默认为NO
        annotationView.draggable = YES;          //设置标注可以拖动,默认为NO
        return annotationView;
    }  
    return nil;  
} 
3运行程序,在地图显示对应的标注点,点击标注弹出气泡,效果如图:
ios_map_draw_1.png
删除默认样式的点标记

通过以上几步简单的操作,您就可以实现在地图上默认样式的点标记了,相应的删除标注方法如下:
if (annotation != nil) {    
    [_mapView removeAnnotation:annotation];    
}
添加自定义样式点标记

iOS SDK可自定义标注(包括 自定义标注图标自定义气泡图标),均通过BMKAnnotationView来实现。

1自定义标注图标

若大头针样式的标注不能满足您的需求,您可以自定义标注图标。

步骤如下:

(1) 添加标注数据对象,可参考大头针标注的步骤(1)【添加默认样式标记->viewDidAppear方法中添加如下所示代码添加标注数据对象】。

(2) 导入标记图片文件到工程中。这里我们导入一个名为 poi.png 的图片文件。

(3) 在 <BMKMapViewDelegate>协议的回调函数mapView:viewForAnnotation:中修改 BMKAnnotationView对应的标注图片。

示例代码如下:

- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[BMKPointAnnotation class]])
    {
        static NSString *reuseIndetifier = @"annotationReuseIndetifier";
        BMKAnnotationView *annotationView = (BMKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
        if (annotationView == nil)
        {
            annotationView = [[BMKAnnotationView alloc] initWithAnnotation:annotation
                                                          reuseIdentifier:reuseIndetifier];
        }
        annotationView.image = [UIImage imageNamed:@"poi.png"];
        return annotationView;
    }
    return nil;
}

运行程序,标注点更换了图标,如下所示:

ios_map_draw_12.png

2添加自定义气泡

气泡在iOS中又称为paopaoView,它由背景和气泡内容构成。

每个气泡显示的内容是根据您的需求定义的,这里我们按照如上图所示的气泡介绍实现一个自定义气泡的步骤,由于是高度自定义内容,以下文档中仅提供OC语言的示例:

(1) 新建自定义气泡类 CustomPaopaotView,继承 UIView。

(2) 在 CustomPaopaotView.h 中定义数据属性,包含:图片、商户名和商户地址。

@interface CustomPaopaotView : UIView
@property (nonatomic, strong) UIImage *image; //商户图
@property (nonatomic, copy) NSString *title; //商户名
@property (nonatomic, copy) NSString *subtitle; //地址
@end

(3) 在CustomPaopaotView.m中重写UIView的drawRect方法,绘制弹出气泡的背景。

#pragma mark - draw rect

- (void)drawRect:(CGRect)rect
{    
    [self drawInContext:UIGraphicsGetCurrentContext()];
    
    self.layer.shadowColor = [[UIColor blackColor] CGColor];
    self.layer.shadowOpacity = 1.0;
    self.layer.shadowOffset = CGSizeMake(0.0f, 0.0f);
}

- (void)drawInContext:(CGContextRef)context
{
    CGContextSetLineWidth(context, 2.0);
    CGContextSetFillColorWithColor(context, [UIColor colorWithRed:0.3 green:0.3 blue:0.3 alpha:0.8].CGColor);
    
    [self getDrawPath:context];
    CGContextFillPath(context);
}
- (void)getDrawPath:(CGContextRef)context
{
    CGRect rrect = self.bounds;
    CGFloat radius = 6.0;
    CGFloat minx = CGRectGetMinX(rrect),
    midx = CGRectGetMidX(rrect),
    maxx = CGRectGetMaxX(rrect);
    CGFloat miny = CGRectGetMinY(rrect),
    maxy = CGRectGetMaxY(rrect)-kArrorHeight;
    
    CGContextMoveToPoint(context, midx+kArrorHeight, maxy);
    CGContextAddLineToPoint(context,midx, maxy+kArrorHeight);
    CGContextAddLineToPoint(context,midx-kArrorHeight, maxy);
    
    CGContextAddArcToPoint(context, minx, maxy, minx, miny, radius);
    CGContextAddArcToPoint(context, minx, minx, maxx, miny, radius);
    CGContextAddArcToPoint(context, maxx, miny, maxx, maxx, radius);
    CGContextAddArcToPoint(context, maxx, maxy, midx, maxy, radius);
    CGContextClosePath(context);
}

(4) 定义用于显示气泡内容的控件,并添加到SubView中。

如上图所示气泡,我们需要一个UIImageView和两个UILabel,添加方法如下:

#define kPortraitMargin     5
#define kPortraitWidth      70
#define kPortraitHeight     50
#define kTitleWidth         120
#define kTitleHeight        20

@interface CustomPaopaotView ()

@property (nonatomic, strong) UIImageView *portraitView;
@property (nonatomic, strong) UILabel *subtitleLabel;
@property (nonatomic, strong) UILabel *titleLabel;
@end
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor clearColor];
    }
    return self;
}

- (void)initSubViews
{
    // 添加图片,即商户图
    self.portraitView = [[UIImageView alloc] initWithFrame:CGRectMake(kPortraitMargin, kPortraitMargin, kPortraitWidth, kPortraitHeight)];
    
    self.portraitView.backgroundColor = [UIColor blackColor];
    [self addSubview:self.portraitView];
    
    // 添加标题,即商户名
    self.titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kPortraitMargin * 2 + kPortraitWidth, kPortraitMargin, kTitleWidth, kTitleHeight)];
    self.titleLabel.font = [UIFont boldSystemFontOfSize:14];
    self.titleLabel.textColor = [UIColor whiteColor];
    self.titleLabel.text = self.title;
    [self addSubview:self.titleLabel];
    
    // 添加副标题,即商户地址
    self.subtitleLabel = [[UILabel alloc] initWithFrame:CGRectMake(kPortraitMargin * 2 + kPortraitWidth, kPortraitMargin * 2 + kTitleHeight, kTitleWidth, kTitleHeight)];
    self.subtitleLabel.font = [UIFont systemFontOfSize:12];
    self.subtitleLabel.textColor = [UIColor lightGrayColor];
    self.subtitleLabel.text = self.subtitle;
    [self addSubview:self.subtitleLabel];
}

(5) 在CustomCalloutView.m中给控件传入数据。

- (void)setTitle:(NSString *)title
{
    self.titleLabel.text = title;
}

- (void)setSubtitle:(NSString *)subtitle
{
    self.subtitleLabel.text = subtitle;
}

- (void)setImage:(UIImage *)image
{
    self.portraitView.image = image;
}
以上就是自定义气泡的全部过程。
添加自定义AnnotationView

创建了自定义气泡后,在点击标注时实现弹出自定义的气泡的效果,还需要以下【添加自定义AnnotationView】的步骤。

由于是高度自定义内容,以下文档中仅提供OC语言的示例:

(1) 新建类CustomAnnotationView,继承BMKAnnotationView或BMKPointAnnotationView。若继承BMKAnnotationView,则需要设置标注图标;若继承BMKPointAnnotationView,使用默认的大头针标注;

(2) 在CustomAnnotationView.h中定义自定义气泡属性;

代码如下所示:

@interface CustomAnnotationView : BMKAnnotationView 
@property (nonatomic, readonly) CustomPaopaotView *paopaoView;
@end

(3) 在CustomAnnotationView.m中修改paopaoView属性;

代码如下所示:

@interface CustomAnnotationView ()
@property (nonatomic, strong, readwrite) CustomPaopaotView *paopaoView;
@end

(4) 重写选中方法setSelected。选中时新建并添加paopaoView,传入数据;非选中时删除paopaoView;

 - (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    if (self.selected == selected)
    {
        return;
    }
    
    if (selected)
    {
        if (self.paopaoView == nil)
        {
            
            /* Construct custom callout. */
            self.paopaoView = [[CustomPaopaotView alloc] initWithFrame:CGRectMake(0, 0, kCalloutWidth, kCalloutHeight)];
            self.paopaoView.center = CGPointMake(CGRectGetWidth(self.bounds) / 2.f + self.calloutOffset.x,
                                                  -CGRectGetHeight(self.paopaoView.bounds) / 2.f + self.calloutOffset.y);
            
            self.paopaoView.image = [UIImage imageNamed:@"poi.png"];
            self.paopaoView.title = self.annotation.title;
            self.paopaoView.subtitle = self.annotation.subtitle;
        }
        
        [self addSubview:self.paopaoView];
    }
    else
    {
        [self.paopaoView removeFromSuperview];
    }
    
    [super setSelected:selected animated:animated];
}

(5) 修改ViewController.m,在BMKMapViewDelegate的回调方法mapView:viewForAnnotation中的修改annotationView的类型。
代码如下:

- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation
{
    if ([annotation isKindOfClass:[BMKPointAnnotation class]])
    {
        static NSString *reuseIndetifier = @"annotationReuseIndetifier";
        CustomAnnotationView *annotationView = (CustomAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuseIndetifier];
        if (annotationView == nil)
        {
            annotationView = [[CustomAnnotationView alloc] initWithAnnotation:annotation
                                                          reuseIdentifier:reuseIndetifier];
            annotationView.canShowCallout = NO;
        }
        
        annotationView.image = [UIImage imageNamed:@"poi.png"];
        return annotationView;
    }
    return nil;
}

运行程序,效果如下:
ios_map_draw_11.png

批量操作Annotation

批量添加Annotation

/**
 *向地图窗口添加一组标注,需要实现BMKMapViewDelegate的-mapView:viewForAnnotation:函数来生成标注对应的View
 *@param annotations 要添加的标注数组
 */
- (void)addAnnotations:(NSArray *)annotations;

批量删除Annotation

/**
 *移除一组标注
 *@param annotation 要移除的标注数组
 */
- (void)removeAnnotations:(NSArray *)annotations;
点聚合
自v2.9.0版本起,新增点聚合功能,可通过缩小地图层级,将定义范围内的多个标注点,聚合显示成一个标注点,解决加载大量点要素到地图上产生覆盖现象的问题,并提高性能。已在Demo中开放源码,方便开发者自行修改。
添加点聚合的方法:
1声明点聚合管理类为全局变量,并初始化,核心代码如下
BMKClusterManager *_clusterManager;//点聚合管理类
 
//初始化点聚合管理类
 
_clusterManager = [[BMKClusterManager alloc] init];
    
2向点聚合管理类中添加点,核心代码如下
CLLocationCoordinate2D coor = CLLocationCoordinate2DMake(39.915, 116.404);
    //向点聚合管理类中添加标注
    for (NSInteger i = 0; i < 20; i++) {
        double lat =  (arc4random() % 100) * 0.001f;
        double lon =  (arc4random() % 100) * 0.001f;
        BMKClusterItem *clusterItem = [[BMKClusterItem alloc] init];
        clusterItem.coor = CLLocationCoordinate2DMake(coor.latitude + lat, coor.longitude + lon);
        [_clusterManager addClusterItem:clusterItem];
    }
3获取聚合后的点,并添加到地图中,核心代码如下
///获取聚合后的标注
    NSArray *array = [_clusterManager getClusters:_clusterZoom];
    NSMutableArray *clusters = [NSMutableArray array];
    for (BMKCluster *item in array) {
        ClusterAnnotation *annotation = [[ClusterAnnotation alloc] init];
        annotation.coordinate = item.coordinate;
        annotation.size = item.size;
        annotation.title = [NSString stringWithFormat:@"我是%ld个", item.size];
        [clusters addObject:annotation];
    }
    [_mapView removeAnnotations:_mapView.annotations];
    [_mapView addAnnotations:clusters];

具体源码请在ClusterDemo中查看。