如下内容转载自面糊的文章《实现物流场景的小车Marker指向目的地》做者:面糊git
连接:https://www.jianshu.com/p/f79...ide
来源:简书函数
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。ui
快递物流相关APP中,如快递、送餐,能够让快递车Marker的车头,在途经点始终指向目的地,以下图所示:
使用技术:腾讯地图iOS SDK,点标记和绘制线spa
核心点:3d
一、操做QPointAnnotation的坐标代理
二、从mapView中获取途经点QPointAnnotation的坐标code
三、经过三角函数计算途经点坐标与终点坐标的角度orm
四、操做QAnnotationView的transform属性blog
代码示例以下:
一、示例展现福州送至北京,途径西安、西宁、济南、太原、天津,先将这几个点的maker添加到地图中:
// 福州 locations[0] = CLLocationCoordinate2DMake(26.101797,119.415539); // 西安 locations[1] = CLLocationCoordinate2DMake(34.475422,109.0005); // 西宁 locations[2] = CLLocationCoordinate2DMake(36.69099,101.749523); // 济南 locations[3] = CLLocationCoordinate2DMake(36.761434,117.174328); // 太原 locations[4] = CLLocationCoordinate2DMake(37.949064,112.56007); // 天津 locations[5] = CLLocationCoordinate2DMake(39.117802,117.174328); // 北京 locations[6] = CLLocationCoordinate2DMake(39.897614,116.383312); // 福州 QPointAnnotation *nnAnnotation = [[QPointAnnotation alloc] init]; nnAnnotation.coordinate = locations[0]; [self.mapView addAnnotation:nnAnnotation]; ....
二、添加小车marker,以福州为起始点:
_carAnnotation = [[QPointAnnotation alloc] init]; _carAnnotation.coordinate = locations[0]; // 指定userData自定义数据,用于判断marker的类型 _carAnnotation.userData = @"car"; [self.mapView addAnnotation:_carAnnotation];
三、实现mapView代理方法,根据userData来区分不一样的Marker
- (QAnnotationView *)mapView:(QMapView *)mapView viewForAnnotation:(id<QAnnotation>)annotation { static NSString *reuse = @"annotation"; static NSString *reuseCar = @"annotationCar"; QPinAnnotationView *annotationView = (QPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:reuse]; if (annotationView == nil) { if (annotation == _carAnnotation) { annotationView = [[QPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseCar]; annotationView.image = [UIImage imageNamed:@"car"]; // 将小车的AnnotationView保存为属性,用于操做转向 _carAnnotationView = annotationView; } else { annotationView = [[QPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuse]; } } return annotationView; }
四、根据三角函数,计算起点和终点的角度,并调整小车Marker的角度
- (void)annotationRotate { // 取出终点坐标位置 CLLocationCoordinate2D toCoord = _bjAnnotation.coordinate; double fromLat = _carAnnotation.coordinate.latitude; double fromlon = _carAnnotation.coordinate.longitude; double toLat = toCoord.latitude; double tolon = toCoord.longitude; double slope = ((toLat - fromLat) / (tolon - fromlon)); double radio = atan(slope); double angle = 180 * (radio / M_PI); if (slope > 0) { if (tolon < fromlon) { angle = -90 - angle; } else { angle = 90 - angle; } } else if (slope == 0) { if (tolon < fromlon) { angle = -90; } else { angle = 90; } } else { if (toLat < fromLat) { angle = 90 - angle; } else { angle = -90 - angle; } } // 这里要注意,计算出来的是角度,而旋转则须要先转换为弧度 _carAnnotationView.transform = CGAffineTransformMakeRotation((M_PI * (angle) / 180.0)); }
在这个基础上,我在navigationItem中添加了一个切换当前途径点的功能,每次点击按钮就会将小车移动到下一个途经点,示例代码以下:
- (void)handleTestAction { _index++; if (_index == self.mapView.annotations.count - 2) { _index = 0; } QPointAnnotation *annotation = self.mapView.annotations[_index]; _carAnnotation.coordinate = annotation.coordinate; [self annotationRotate]; }
效果示例以下图所示: