首先看下高德默认的小蓝点效果
再来看下我们产品要实现的效果
有没有熟悉的感觉,没错,就是模仿keep的,我们的产品真的是对keep大爱啊。
要自定义定位点,首先要展示当前定位点,用到这个属性,设置为YES
///是否显示用户位置
@property (nonatomic) BOOL showsUserLocation;
对于当前定位点来说,它也是一个MAAnnotation
标注,但是高德对它单独封装了一个类,继承自MAAnnotation
,叫做MAUserLocation
。我们设置了showsUserLocation
为YES之后,只要在这个代理方法里面对该类型标注进行处理,即能实现自定义效果。
/**
* @brief 根据anntation生成对应的View
* @param mapView 地图View
* @param annotation 指定的标注
* @return 生成的标注View
*/
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id )annotation;
然后我们先来设置一张图片,替换掉它官方的白底蓝色呼吸点,看看什么效果
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)annotation
{
if ([annotation isKindOfClass:[MAUserLocation class]]) {
static NSString *userLocationStyleReuseIndetifier = @"userLocationStyleReuseIndetifier";
MAAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:userLocationStyleReuseIndetifier];
if (annotationView == nil) {
annotationView = [[MAPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:userLocationStyleReuseIndetifier];
}
annotationView.image = [UIImage imageNamed:@"icon_tracking_userLocation"];
self.userLocationAnnotationView = annotationView;
return annotationView;
}
return nil;
}
替换了张图片,效果出来了,但是,这个呼吸效果呢,哪个白点呢!!!
少年,你还是太天真,你以为这样换张图片就能搞定?!图样图森破!
这个放着,我们先来优化下这个图标。首先,箭头出来,就表示需要根据方位指示。
我们只要获取到当前定位点的定位信息,拿出来方向的值,处理下即可。
首先,声明一个标注属性
@property (nonatomic, strong) MAAnnotationView *userLocationAnnotationView;
前面我们在- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id
的方法里面已经关联到了自定义的定位点
self.userLocationAnnotationView = annotationView;
然后再定位回调里面如下设置,就能实时指示当前方位。
- (void)mapView:(MAMapView *)mapView didUpdateUserLocation:(MAUserLocation *)userLocation updatingLocation:(BOOL)updatingLocation
{
if (!updatingLocation && self.userLocationAnnotationView != nil) {
[UIView animateWithDuration:0.1 animations:^{
double degree = userLocation.heading.trueHeading - self.mapView.rotationDegree;
self.userLocationAnnotationView.transform = CGAffineTransformMakeRotation(degree * M_PI / 180.f );
}];
}
}
那么问题来了,那个呼吸的白底圆点呢???!!!
少年,不要心急,下面就来说说这个实现。
既然定位点是个标注MAAnnotationView
,先点进去文件看看,没有啥相关的设置,那就只能继承MAAnnotationView
自定义标注了。
首先把customizeUserLocationAccuracyCircleRepresentation
这是为YES
@property (nonatomic) BOOL customizeUserLocationAccuracyCircleRepresentation;
然后新建一个类,继承自MAAnnotationView
#import
@interface YTUserLocationAnnotationView : MAAnnotationView
@end
接着代理方法里面修改下类
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id)annotation
{
if ([annotation isKindOfClass:[MAUserLocation class]]) {
static NSString *userLocationStyleReuseIndetifier = @"userLocationStyleReuseIndetifier";
YTUserLocationAnnotationView *annotationView = (YTUserLocationAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:userLocationStyleReuseIndetifier];
if (annotationView == nil) {
annotationView = [[YTUserLocationAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:userLocationStyleReuseIndetifier];
}
annotationView.image = [UIImage imageNamed:@"icon_tracking_userLocation"];
self.userLocationAnnotationView = annotationView;
//为了让位置点永远在图层最上面,设置选定图标。
//高德SDK5.4.0必须在主线程选定图标,否则会导致界面进入地图加载卡死,暂时不懂为何
dispatch_async(dispatch_get_main_queue(), ^{
[self.mapView selectAnnotation:annotation animated:NO];
});
return annotationView;
}
return nil
}
在自定义的定位点类里面实现didMoveToSuperview
方法,当 annotation 被添加到地图上就会触发,然后就可以执行需要的动画了,具体实现如下。
#import "YTUserLocationAnnotationView.h"
@interface YTUserLocationAnnotationView ()
@property (nonatomic, strong) CALayer *circleView;
@end
@implementation YTUserLocationAnnotationView
- (CALayer *)circleView
{
if (!_circleView) {
_circleView = [CALayer layer];
_circleView.frame = CGRectMake(0, 0, self.ab_width + 6, self.ab_height + 6);
_circleView.position = self.imageView.center;
_circleView.backgroundColor = [UIColor whiteColor].CGColor;
_circleView.cornerRadius = _circleView.frame.size.width / 2;
[self.layer insertSublayer:_circleView below:self.imageView.layer];
}
return _circleView;
}
- (void)didMoveToSuperview
{
[super didMoveToSuperview];
[self startAnimate];
}
- (void)startAnimate
{
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.scale"];
animation.fromValue = [NSNumber numberWithFloat:1.0f];
animation.toValue = [NSNumber numberWithFloat:2.2f];
animation.autoreverses = YES;
animation.duration = 1.f;
animation.repeatCount = MAXFLOAT;
animation.removedOnCompletion = NO;
animation.fillMode = kCAFillModeForwards;
animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
[self.circleView addAnimation:animation forKey:nil];
}
- (void)dealloc
{
DLog(@"%s",__func__);
}
掌握了这个小技巧,你也能实现各种各样的定位点展示UI。