项目中有需求需要实现车辆在地图上的行车轨迹,就像uber上小车移动的动效一样。刚接到需求时以为很简单,timer获取到车辆的经纬度及车头方向后两次tansform仿射变换,先transform方向动画再transform移动动画。
想向是美好的,实际中发现以下问题:
- transform 旋转角度后坐标系发生变化了在这个基础上再进行位置的transform会有很大的偏移;具体参考iOS中的图形变换
- 百度地图在移动显示区域重绘时会将之前的annotationview的状态清除,设置小车annotationview的tansformmakerotate后移动地图又还原成了原来的初始状态
- 将coordinate转换成百度地图坐标后再进行位移动画,动画结束后改变annotation的coordinate发现会有一点小偏移。
思考无果情况下决定利用Reveal查看下Uber的页面元素一探究竟:
可以发现,Uber的实现是在ONEDriverAnnotationView下自己添加了一个子的UIImageView,设置车辆方向时针对子UIImageView进行旋转,位移动画交由ONEDriverAnnotationView实现。
代码如下:
// 设置自定义标注样式
- (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation {
//设置司机标注视图
if ([annotation.title isEqualToString:kBusAnnotaionText]) {
NSString *AnnotationViewID = @"renameMark";
//DuMapBusAnnotationView继承自BMKMapAnnotationView,添加busImageView属性
DuMapBusAnnotationView *annotationView = (DuMapBusAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:AnnotationViewID];
if (annotationView == nil)
{
annotationView = [[DuMapBusAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:AnnotationViewID];
annotationView.image = [UIImage imageNamed:@"bus_backView"];
annotationView.busImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(annotationView.frame), CGRectGetHeight(annotationView.frame))];
// bus_backView图片与bus图片大小一样,但内容为全透明
annotationView.busImageView.image = [UIImage imageNamed:@"bus"];
[annotationView addSubview:annotationView.busImageView];
annotationView.canShowCallout = NO;
// 提升annotationview层级防止被遮挡
[annotationView.superview bringSubviewToFront:annotationView];
}
self.busAnnotationView = annotationView;
return annotationView;
}
return nil;
}
// 更新车辆位置动画,在定时器中重复调用
- (void)updateBusLocation {
//移除旧的
if (_busLatitude <= 0 || _busLongitude <= 0) {
[_DUMapView removeAnnotation:_busWhereAnnotaion];
return;
}
if (![_DUMapView.annotations containsObject:_busWhereAnnotaion]) {
[_DUMapView addAnnotation:_busWhereAnnotaion];
CLLocationCoordinate2D coor;
coor.latitude = _busLatitude;
coor.longitude = _busLongitude;
_busWhereAnnotaion.coordinate = coor;
}
CLLocationCoordinate2D coor;
coor.latitude = _busLatitude;
coor.longitude = _busLongitude;
[UIView animateWithDuration:0.25 animations:^{
// 对子视图busImageView进行旋转动画
self.busAnnotationView.busImageView.transform = CGAffineTransformMakeRotation(self.course*M_PI/180);
} completion:^(BOOL finished) {
[UIView animateWithDuration:2.5 animations:^{
// 更新coordinate即可进行位移动画
self.busWhereAnnotaion.coordinate = coor;
} completion:^(BOOL finished) {
// do something else
}];
}];
}
Demo下载 2016.2.6