绘制点标记

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

地图 SDK 提供的点标记功能包含两大部分,一部分是点(Annotation)、另一部分是浮于点上方的信息窗体(CalloutView)。

AnnotationCalloutView 有默认风格,同时也支持自定义。以下只展示一些基础功能的使用,详细内容可分别参考官方Demo。

1.添加默认样式标记

iOS SDK预置了基本的标注点(FMGLPointAnnotation)和一个大头针标注 View( FMGLAnnotationView ),您可以直接使用来显示标注。

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

(1)viewDidAppear方法中添加如下所示代码添加标注数据对象。

FMGLPointAnnotation *point = [[FMGLPointAnnotation alloc] init];
point.coordinate = coor;
// 必须实现
point.title = @"主标题";
point.subtitle = @"副标题";
[self.mapView addAnnotation:point];

(2)在<FMGLMapViewDelegate>协议中的mapView:viewForAnnotation:回调函数无需实现,或者函数返回nil,系统自动返回默认样式标记。

(3)实现<FMGLMapViewDelegate>协议中的mapView:annotationCanShowCallout:回调函数,控制信息窗体是否弹出。

(4)运行程序,在地图显示对应的标注点,点击标注弹出气泡,效果如图:

MapDraw_image1

删除默认样式的点标记

通过以上几步简单的操作,您就可以实现在地图上默认样式的点标记了,相应的删除标注方法如下:

if (annotation != nil) {    
    [_mapView removeAnnotation:annotation];    
}

2.添加自定义样式点标记

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

自定义标注图标

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

步骤如下:

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

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

(3) 在 <FMGLMapViewDelegate>协议的回调函数mapView:imageForAnnotation:中创建相应图片的标注(回调方法只适用于替换标注图片)。

示例代码如下:

- (nullable FMGLAnnotationImage *)mapView:(FMGLMapView *)mapView imageForAnnotation:(id <FMGLAnnotation>)annotation
{
    if ([annotation isKindOfClass:[FMGLPointAnnotation class]]) {
        // 自定义标注
        static NSString *AnnotationViewID = @"customAnnotation";
        FMGLAnnotationImage *annotationView = [self.mapView dequeueReusableAnnotationImageWithIdentifier:AnnotationViewID];
        if (annotationView == nil) {
            annotationView = [FMGLAnnotationImage annotationImageWithImage:[UIImage imageNamed:@"CustomAnnotation_icon"] reuseIdentifier:AnnotationViewID];
        }
        return annotationView;
    }
    return nil;
}

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

MapDraw_image2

添加自定义AnnotationView

自定义AnnotationView是高度自定义标注。

(1) 新建类 CustomAnnotationView ,继承 FMGLAnnotationView

(2) 在 CustomAnnotationView.h 中定义自定义 titleLabimageView。 代码如下所示:

@interface CustomAnnotationView : FMGLAnnotationView

@property (nonatomic, strong) UIImageView *imageView;
@property (nonatomic, strong) UILabel *titleLab;

@end

(3) 在CustomAnnotationView.m中自定义标注的内容;

代码如下所示:

- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithReuseIdentifier:reuseIdentifier];
    if (self) {
        [self setBounds:CGRectMake(0.f, 0.f, 150.f, 50.f)];

        [self setBackgroundColor:[UIColor cyanColor]];

        _imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 50, 50)];
        _imageView.contentMode = UIViewContentModeScaleAspectFit;
        _imageView.image = [UIImage imageNamed:@"CustomAnnotation_icon"];
        [self addSubview:_imageView];

        _titleLab = [[UILabel alloc] initWithFrame:CGRectMake(50, 0, 100, 50)];
        _titleLab.textColor = [UIColor blackColor];
        _titleLab.numberOfLines = 0;
        _titleLab.text = @"自定义标注";
        [self addSubview:_titleLab];
    }

    return self;
}

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

(5) 在 <FMGLMapViewDelegate>协议的回调函数mapView:viewForAnnotation:中创建相应标注。

运行程序,标注点替换为自定的AnnotationView,如下所示:

MapDraw_image3

添加自定义气泡

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

每个气泡显示的内容是根据您的需求定义的,这里我们介绍实现一个自定义气泡的步骤,由于是高度自定义内容,以下内容为示例:

(1) 新建自定义气泡类 CustomCalloutView ,继承 UIView,<FMGLCalloutView>协议。

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

// FMGLCalloutView 必须实现
@property (nonatomic, strong) id <FMGLAnnotation> representedObject;
@property (nonatomic, strong) UIView *leftAccessoryView;
@property (nonatomic, strong) UIView *rightAccessoryView;
@property (nonatomic, weak) id<FMGLCalloutViewDelegate> delegate;


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

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

- (void)drawRect:(CGRect)rect
{
    UIColor *fillColor = [UIColor colorWithWhite:0.7 alpha:1.0];

    CGFloat tipLeft = rect.origin.x + (rect.size.width / 2.0) - (tipWidth / 2.0);
    CGPoint tipBottom = CGPointMake(rect.origin.x + (rect.size.width / 2.0), rect.origin.y +rect.size.height);
    CGFloat heightWithoutTip = rect.size.height - tipHeight;

    // draw the white background with tip
    CGContextRef ctxt = UIGraphicsGetCurrentContext();

    CGMutablePathRef tipPath = CGPathCreateMutable();
    CGPathMoveToPoint(tipPath, NULL, 0, 0);
    CGPathAddLineToPoint(tipPath, NULL, 0, heightWithoutTip);
    CGPathAddLineToPoint(tipPath, NULL, tipLeft, heightWithoutTip);
    CGPathAddLineToPoint(tipPath, NULL, tipBottom.x, tipBottom.y);
    CGPathAddLineToPoint(tipPath, NULL, tipLeft + tipWidth, heightWithoutTip);
    CGPathAddLineToPoint(tipPath, NULL, CGRectGetWidth(rect), heightWithoutTip);
    CGPathAddLineToPoint(tipPath, NULL, CGRectGetWidth(rect), 0);
    CGPathCloseSubpath(tipPath);

    [fillColor setFill];
    CGContextAddPath(ctxt, tipPath);
    CGContextFillPath(ctxt);
    CGPathRelease(tipPath);
}

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

static CGFloat const tipHeight = 10.0;
static CGFloat const tipWidth = 10.0;

#define kPortraitMargin     5
#define kPortraitWidth      70
#define kPortraitHeight     50

#define kTitleWidth         120
#define kTitleHeight        20

#define CalloutViewWidth 200
#define CalloutViewHeight 80

@interface CustomCalloutView ()

@property (nonatomic, strong) UIImageView *portraitView;
@property (nonatomic, strong) UILabel *subtitleLabel;
@property (nonatomic, strong) UILabel *titleLabel;

@end

@implementation CustomCalloutView


- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self)
    {
        self.backgroundColor = [UIColor clearColor];
        [self initSubViews];
    }
    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 = @"titletitletitletitle";
    [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 whiteColor];
    self.subtitleLabel.text = @"subtitleLabelsubtitleLabelsubtitleLabel";
    [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;
}

(6) 在CustomCalloutView.m中实现 FMGLCalloutView 的协议方法presentCalloutFromRect:inView:constrainedToView:animated:

- (void)presentCalloutFromRect:(CGRect)rect inView:(UIView *)view constrainedToView:(UIView *)constrainedView animated:(BOOL)animated
{
    if ([self.delegate respondsToSelector:@selector(calloutViewWillAppear:)])
    {
        [self.delegate performSelector:@selector(calloutViewWillAppear:) withObject:self];
    }

    [view addSubview:self];

    CGFloat frameOriginX = rect.origin.x + (rect.size.width/2.0) - (CalloutViewWidth/2.0);
    CGFloat frameOriginY = rect.origin.y - CalloutViewHeight;
    self.frame = CGRectMake(frameOriginX, frameOriginY,
                            CalloutViewWidth, CalloutViewHeight);

    if ([self.delegate respondsToSelector:@selector(calloutViewDidAppear:)])
    {
        [self.delegate performSelector:@selector(calloutViewDidAppear:) withObject:self];
    }
}

(7) 修改ViewController.m,在 FMGLMapViewDelegate 的回调方法mapView:viewForAnnotation中的修改 annotationView 的类型

代码如下

- (UIView<FMGLCalloutView> *)mapView:(FMGLMapView *)mapView calloutViewForAnnotation:(id<FMGLAnnotation>)annotation
{

    if ([annotation isKindOfClass:[FMGLPointAnnotation class]]) {
        // 自定义标注
        static NSString *AnnotationViewID = @"customAnnotation";
        CustomCalloutView *annotationView = (CustomCalloutView *)[self.mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
        if (annotationView == nil) {
            annotationView = [[CustomCalloutView alloc] init];
        }
        annotationView.representedObject = annotation;
        annotationView.image = [UIImage imageNamed:@"CustomAnnotation_icon"];
        annotationView.title = @"主标题";
        annotationView.subtitle = @"副标题";

        return annotationView;
    }
    return nil;
}

运行程序,效果如下:

MapDraw_image4

results matching ""

    No results matching ""