绘制点标记
点标记用来在地图上标记任何位置,例如用户位置、车辆位置、店铺位置等一切带有位置属性的事物。
地图 SDK 提供的点标记功能包含两大部分,一部分是点(Annotation
)、另一部分是浮于点上方的信息窗体(CalloutView
)。
Annotation
和 CalloutView
有默认风格,同时也支持自定义。以下只展示一些基础功能的使用,详细内容可分别参考官方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)运行程序,在地图显示对应的标注点,点击标注弹出气泡,效果如图:
删除默认样式的点标记
通过以上几步简单的操作,您就可以实现在地图上默认样式的点标记了,相应的删除标注方法如下:
if (annotation != nil) {
[_mapView removeAnnotation:annotation];
}
2.添加自定义样式点标记
iOS SDK可自定义标注(包括 自定义标注图标 和 自定义气泡图标),通过 FMGLAnnotationView
,FMGLAnnotationImage
和 FMGLCalloutView
来实现。
自定义标注图标
若大头针样式的标注不能满足您的需求,您可以自定义标注图标。
步骤如下:
(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;
}
运行程序,标注点更换了图标,如下所示:
添加自定义AnnotationView
自定义AnnotationView
是高度自定义标注。
(1) 新建类 CustomAnnotationView
,继承 FMGLAnnotationView
。
(2) 在 CustomAnnotationView.h
中定义自定义 titleLab
和 imageView
。
代码如下所示:
@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
,如下所示:
添加自定义气泡
气泡在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
中重写UIView
的drawRect
方法,绘制弹出气泡的背景。
- (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;
}
运行程序,效果如下: