iOS 平滑移动大头针视图 (类似滴滴和 UBER)
2017-01-16 09:08
351 查看
大家都知道,地图上的大头针视图如果想平滑的从一个坐标点移动到另一个坐标点,重新添加一个大头针是无法实现这种效果的,那样不会有一个移动效果,如果想达到类似滴滴车辆平滑移动效果,就必须在同一个大头针对象中改变它的坐标,大头针的视图方向也要根据新的角度改变他的视图角度.
我们这里新建一个
主要说说自定义大头针,大头针分
和
如果需要自定义大头针, 需要遵守
在自定义的大头针里面我们添加几个自定义属性
其中
在 .m 文件中自定义几个内部属性
在大头针的初始化方法中,监听定位通知,初始化保存定位的数组
在监听的通知中, 我们保存获取到的定位对象,为了保证大头针的移动效果,我们需要在建一个移动的数组,这个移动数组保证有一定量的定位数据才开始移动动画效果,而定位数组只负责把所有获取到的定位对象保存下来
核心的移动大头针方法,使用递归的方式一次次的移动大头针,在移动数组全部使用后结束递归,等待新获取到的数组
只能需要注意的几个细节,一个是大头针角度,在
这里要用到的速度和两个坐标点的距离用来设定车辆移动动画的时间,这样可以保证车辆的移动速度是均匀的平滑的.
我们在每次动画后把创建的
大头针的平滑移动,只需使用
项目 DEMO : https://github.com/ZeroJian/SmoothMovingAnnotation
我们这里新建一个
LocationManager类用来获取用户的坐标,当然如果业务需求是服务器获取,实现思路类似,只是改变一下坐标点的获取方式.具体
LocationManager单例的创建细节就不多说了,我们在获取到用户位置的回调里面添加一个通知
- (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray<CLLocation *=""> *)locations { CLLocation *location = locations.firstObject; [[NSNotificationCenter defaultCenter] postNotificationName:kdidUpdateLocation object:location]; }</CLLocation>
主要说说自定义大头针,大头针分
MKAnnotationView用来显示大头针视图,
和
MKAnnotation用来设置大头针的一些属性,可以简单的把它看成一个
view - model的关系
如果需要自定义大头针, 需要遵守
BKAnnotation协议,其中
coordinate属性是必须实现的属性
@protocol MKAnnotation <NSObject> // Center latitude and longitude of the annotation view. // The implementation of this property must be KVO compliant. @property (nonatomic, readonly) CLLocationCoordinate2D coordinate; @optional // Title and subtitle for use by selection UI. @property (nonatomic, readonly, copy, nullable) NSString *title; @property (nonatomic, readonly, copy, nullable) NSString *subtitle; // Called as a result of dragging an annotation view. - (void)setCoordinate:(CLLocationCoordinate2D)newCoordinate NS_AVAILABLE(10_9, 4_0); @end</NSObject>
在自定义的大头针里面我们添加几个自定义属性
@property (nonatomic, assign) MyAnnotationType type; @property (nonatomic, assign) double angle; @property (nonatomic, strong) MKAnnotationView *annotationView;
其中
type是一个枚举类型,用来自定义大头针的类型,
angle表示方向,用来显示大头针的方向
在 .m 文件中自定义几个内部属性
NSMutableArray *locations; NSArray *moveArray; BOOL movingOver; NSInteger currentIndex; UIImage *annnationImage;
在大头针的初始化方法中,监听定位通知,初始化保存定位的数组
- (instancetype)initWithType:(MyAnnotationType)type coordinate:(CLLocationCoordinate2D)coordinate angle:(double)angle { if (self == [super init]) { _type = type; _coordinate = coordinate; _angle = angle; if (type == MyAnnotationTypeCar) { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onNotifiedCurrentLocationUpdated:) name:kdidUpdateLocation object:nil]; locations = [[NSMutableArray alloc] initWithCapacity:20]; movingOver = YES; } } return self; }
在监听的通知中, 我们保存获取到的定位对象,为了保证大头针的移动效果,我们需要在建一个移动的数组,这个移动数组保证有一定量的定位数据才开始移动动画效果,而定位数组只负责把所有获取到的定位对象保存下来
- (void)onNotifiedCurrentLocationUpdated:(NSNotification *)notification { if (notification.object) { CLLocation *location = notification.object; [locations addObject:location]; if (locations.count >= 5 && movingOver == YES) { moveArray = [NSArray arrayWithArray:locations]; [locations removeAllObjects]; NSLog(@"----- moveArrayCount: %ld",moveArray.count); NSLog(@"------beging moving -----"); currentIndex = 0; movingOver = NO; [self startMoving]; } } }
核心的移动大头针方法,使用递归的方式一次次的移动大头针,在移动数组全部使用后结束递归,等待新获取到的数组
- (void)startMoving { NSInteger index = currentIndex % moveArray.count; CLLocation *newLocation = moveArray[index]; self.annotationView.image = [annnationImage zj_imageRotatedByAngle:newLocation.course]; CLLocation *currentLocation = [[CLLocation alloc] initWithLatitude:self.coordinate.latitude longitude:self.coordinate.longitude]; double distance = [newLocation distanceFromLocation:currentLocation]; double speed = newLocation.speed; CLLocationCoordinate2D newCoordinate = newLocation.coordinate; [UIView animateWithDuration:distance/speed animations:^{ self.coordinate = newCoordinate; currentIndex ++; } completion:^(BOOL finished) { if (currentIndex == moveArray.count) { movingOver = YES; moveArray = nil; } else { [self startMoving]; } }]; }
只能需要注意的几个细节,一个是大头针角度,在
CLLocation对象里面是有一个角度属性和速度属性的,当然如果只有两个坐标点也是可以通过算法获取到的.
这里要用到的速度和两个坐标点的距离用来设定车辆移动动画的时间,这样可以保证车辆的移动速度是均匀的平滑的.
我们在每次动画后把创建的
index + 1,然后和数组的
count通过取余运算获取到下次递归数组使用的
index
大头针的平滑移动,只需使用
UIView动画简单的把新的坐标赋值给大头针即可实现.
项目 DEMO : https://github.com/ZeroJian/SmoothMovingAnnotation
相关文章推荐
- 类似滴滴打车,多辆小车在地图上平滑移动的实现,基于百度地图实现(无轨迹)
- 类似滴滴打车,多辆小车在地图上平滑移动的实现,基于百度地图实现(轨迹已画好)
- 类似滴滴打车,多辆小车在地图上平滑移动的实现,基于百度地图实现(无轨迹)
- iOS类似支付宝首页Item项的移动排序
- IOS 弹出键盘 移动视图
- IOS开发(88)之动画之视图的移动
- iOS中动画的实现:以及视图的移动、缩放和旋转
- [IOS视图切换]ViewDeck类似path效果的实现
- 移动开发iOS之如何在UI界面实现视图的交替
- iOS开发学习之#表视图#(3)移动行
- IOS之表视图单元格删除、移动及插入
- iOS项目开发实战——制作视图的平移动画以及解决移动异常问题
- Unity3D 游戏引擎之IOS自定义游戏摇杆与飞机平滑的移动(十一)
- [置顶] iOS出现键盘的同时视图向上移动的方法讲解
- iOS键盘高度,键盘弹出视图上移动
- iOS 类似QQ空间表视图下拉头部视图放大效果实现
- mfc下鼠标拖动画面使视图移动的实现方法,类似浏览PDF时用手型鼠标移动视图的效果
- IOS成长之路-使UIView视图缓慢的移动
- IOS之表视图单元格删除、移动及插入
- iOS UI 视图移动及缩放