Des's iOS iOS开发部落项目以及封装

Uber车辆移动动效实现

2017-01-17  本文已影响2401人  xiaoliuTX_iOS

项目中有需求需要实现车辆在地图上的行车轨迹,就像uber上小车移动的动效一样。刚接到需求时以为很简单,timer获取到车辆的经纬度及车头方向后两次tansform仿射变换,先transform方向动画再transform移动动画。
想向是美好的,实际中发现以下问题:

  1. transform 旋转角度后坐标系发生变化了在这个基础上再进行位置的transform会有很大的偏移;具体参考iOS中的图形变换
  2. 百度地图在移动显示区域重绘时会将之前的annotationview的状态清除,设置小车annotationview的tansformmakerotate后移动地图又还原成了原来的初始状态
  3. 将coordinate转换成百度地图坐标后再进行位移动画,动画结束后改变annotation的coordinate发现会有一点小偏移。

思考无果情况下决定利用Reveal查看下Uber的页面元素一探究竟:


image

可以发现,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

上一篇下一篇

猜你喜欢

热点阅读