坑
路线绘制完毕的时候,想要截图,但是死活不能截取到完整的“起点”+“终点”图片,即使在截图之前将地图的centerCoordinate设置成中点,然后设置2s延时后再截图,也还是只能截取到以终点为中点的图片。并不是设置center无效,地图会闪一下中点的位置,然后还是回归到终点的位置,然后截图。但是!但是!当地图加载后,我人为地拉动一下地图,那么在截图的时候,竟然可以设置中点成功,并截取到完整的图片。这个问题纠结了一个礼拜。(问题看不懂的:我搜索了一下如何上传视频,但是貌似简书的markdown不支持视频,但是我又不想用回富文本,所以,只能用文字描述了。)
灵光一闪
今天突然想到将这个设置成no:_mapView.showsUserLocation = NO; 这样的话,就需要自己实现定位图片的一些功能,譬如箭头图标;设备运动方向变化的时候,箭头要跟着指向前进的方向;还有就是随着定位的变化而变化位置。
我猜想的是,百度地图在我停止更新地点然后设置中点的时候,还会在某个回调中将当前位置设置成中点,但是拖动地图打断了它的这种回调。所以,我干脆就不让它来帮我showUserLocation,我自己来显示好了。这样子一改,确实解决了问题。但是在模拟器上开车跑的时候(看本文“收获”小节),结束定位来截图的时候,还有可能会定位到当前位置,导致截图不完整,但这个现象只出现了一次,然后无法重现,所以我暂时先不管了,毕竟我这个App是给用户绘制走路路线的。
关键代码
#pragma mark - update heading
-(void)BMKLocationManager:(BMKLocationManager *)manager didUpdateHeading:(CLHeading *)heading
{
//magneticHeading: 距离磁北方向的角度
//trueHeading: 真北
//headingAccuracy: 如果是负数,代表当前设备朝向不可用
if (heading.headingAccuracy < 0) {
return ;
}
if (!self.userLocation) {
self.userLocation = [[BMKUserLocation alloc] init];
}
self.userLocation.heading = heading;
[self.mapView updateLocationData:self.userLocation];
for (UIView *subView in self.arrowView.subviews) {
if ([subView isKindOfClass:[UIImageView class]] && subView.tag == 10000000) {
//角度,因为箭头图片向右方,所以逆时针转90度
CLLocationDirection angle = heading.magneticHeading-90.f;
//顺时针旋转图片(弧度)
subView.transform = CGAffineTransformMakeRotation(angle*M_PI/180.f);
}
}
}
#pragma mark - update location
-(void)BMKLocationManager:(BMKLocationManager *)manager didUpdateLocation:(BMKLocation *)location orError:(NSError *)error
{
if (error) {
NSLog(@"locError:{%ld - %@};", (long)error.code, error.localizedDescription);
}
if (!location) {
return ;
}
if (!self.userLocation) {
self.userLocation = [[BMKUserLocation alloc] init];
}
self.userLocation.location = location.location;
[self.mapView updateLocationData:self.userLocation];
//地图放缩大小,4-21
self.mapView.zoomLevel = 21;
self.mapView.centerCoordinate = CLLocationCoordinate2DMake(self.userLocation.location.coordinate.latitude, self.userLocation.location.coordinate.longitude);
if (self.arrow) {
[self.mapView removeAnnotation:self.arrow];
}
BMKPointAnnotation *arrow = [[BMKPointAnnotation alloc] init];
arrow.coordinate = CLLocationCoordinate2DMake(self.userLocation.location.coordinate.latitude, self.userLocation.location.coordinate.longitude);
arrow.title = kArrowTitle;
[self.mapView addAnnotation:arrow];
self.arrow = arrow;
if(self.isStartTrace)
{
CGFloat distance = [self.userLocation.location distanceFromLocation:self.firstLocation.location];
if (distance < 10) {
return ;
}
CLLocationCoordinate2D coords[2] = {0};
coords[0].latitude = self.firstLocation.location.coordinate.latitude;
coords[0].longitude = self.firstLocation.location.coordinate.longitude;
coords[1].latitude = location.location.coordinate.latitude;
coords[1].longitude = location.location.coordinate.longitude;
//构建分段颜色索引数组
BMKPolyline *polyline = [BMKPolyline polylineWithCoordinates:coords count:2];
[self.mapView addOverlay:polyline];
[self.points addObject:location];
self.firstLocation = [self.userLocation copy];
}
}
#pragma mark - 绘制轨迹点
-(void)drawTrackWithPoints:(NSArray *)points
{
NSLog(@"points: %@", points);
CLLocationCoordinate2D coors[points.count];
NSInteger cnt = 0;
for (size_t i = 0; i < points.count; i++) {
CLLocationCoordinate2D p = CLLocationCoordinate2DMake(((BMKLocation *)points[i]).location.coordinate.latitude, ((BMKLocation *)points[i]).location.coordinate.longitude);
coors[i] = p;
cnt++;
}
BMKPolyline *line = [BMKPolyline polylineWithCoordinates:coors count:cnt];
//起点annotation
BMKPointAnnotation *startAnnotation = [[BMKPointAnnotation alloc] init];
startAnnotation.coordinate = coors[0];
startAnnotation.title = kStartPositionTitle;
//终点annotation
BMKPointAnnotation *endAnnotation = [[BMKPointAnnotation alloc] init];
endAnnotation.coordinate = coors[cnt-1];
endAnnotation.title = kEndPositionTitle;
dispatch_async(MAIN_QUEUE, ^{
[self.mapView removeOverlays:self.mapView.overlays];
[self.mapView removeAnnotations:self.mapView.annotations];
[self mapViewFitForCoordinates:points];
[self.mapView addOverlay:line];
[self.mapView addAnnotation:startAnnotation];
[self.mapView addAnnotation:endAnnotation];
});
}
#pragma mark - 设置起点、终点和当前点样式
-(BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id<BMKAnnotation>)annotation
{
BMKAnnotationView *view = nil;
if ([annotation.title isEqualToString:kStartPositionTitle]) {
static NSString *startViewID = @"startAnnotationID";
view = [mapView dequeueReusableAnnotationViewWithIdentifier:startViewID];
if (view == nil) {
view = [[BMKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:startViewID];
UILabel *lbl = [self createLabel:@"始"];
[view addSubview:lbl];
}
}
else if([annotation.title isEqualToString:kEndPositionTitle]){
static NSString *endViewID = @"endAnnotationID";
view = [mapView dequeueReusableAnnotationViewWithIdentifier:endViewID];
if (view == nil) {
view = [[BMKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:endViewID];
UILabel *lbl = [self createLabel:@"终"];
[view addSubview:lbl];
}
}
else if([annotation.title isEqualToString:kArrowTitle]){
static NSString *runningArrowID = @"runningArrowAnnotationID";
view = [mapView dequeueReusableAnnotationViewWithIdentifier:runningArrowID];
if (view == nil) {
view = [[BMKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:runningArrowID];
view.frame = CGRectMake(0, 0, 22, 22);
view.draggable = NO;
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 22, 22)];
imageView.transform = CGAffineTransformMakeRotation((self.firstLocation.heading.magneticHeading-90.f)*M_PI/180.f);
imageView.image = [UIImage imageNamed:@"sportArrow.png"];
imageView.tag = 10000000;
[view addSubview:imageView];
}
self.arrowView = view;
}
return view;
}
-(UILabel *)createLabel:(NSString *)text
{
//label的frame x, y需要设置成-15,不然“始”会有一截没有连线的
UILabel *lblStart = [[UILabel alloc] initWithFrame:CGRectMake(-15, -15, 30, 30)];
lblStart.backgroundColor = CSecondaryColor;
lblStart.font = [UIFont systemFontOfSize:14.0];
lblStart.textAlignment = NSTextAlignmentCenter;
lblStart.textColor = [UIColor whiteColor];
lblStart.layer.cornerRadius = 15;
lblStart.layer.borderWidth = 1;
lblStart.layer.masksToBounds = YES;
lblStart.layer.borderColor = [UIColor darkGrayColor].CGColor;
lblStart.text = text;
return lblStart;
}
-(void)mapViewFitForCoordinates:(NSArray *)points
{
double minLat = 90.0;
double maxLat = -90.0;
double minLon = 180.0;
double maxLon = -180.0;
for (size_t i = 0; i < points.count; i++) {
minLat = fmin(minLat, ((BMKLocation *)points[i]).location.coordinate.latitude);
maxLat = fmax(maxLat, ((BMKLocation *)points[i]).location.coordinate.latitude);
minLon = fmin(minLon, ((BMKLocation *)points[i]).location.coordinate.longitude);
maxLon = fmax(maxLon, ((BMKLocation *)points[i]).location.coordinate.longitude);
}
CLLocationCoordinate2D center = CLLocationCoordinate2DMake((minLat+maxLat)*0.5, (minLon+maxLon)*0.5);
BMKCoordinateSpan span;
span.latitudeDelta = 1.2 * ((maxLat-minLat)+0.01);
span.longitudeDelta = 1.2 * ((maxLon - minLon)+0.01);
BMKCoordinateRegion region;
region.center = center;
region.span = span;
[self.mapView setRegion:region animated:YES];
}
收获
-
使用百度地图绘制路线,可以使用模拟器来进行模拟人的走动,或者车跑,或者自定义位置。
打开模拟器,去到导航栏,点击Debug,如下图,
我写了NSMutableArray *overlays和annotations来存储添加的层和线,原来mapview自己会保存,删除的时候使用这个就OK了。
[self.mapView removeOverlays:self.mapView.overlays];
[self.mapView removeAnnotations:self.mapView.annotations];