美文网首页
iOS使用百度地图绘制轨迹遇到的坑

iOS使用百度地图绘制轨迹遇到的坑

作者: 蜗牛你慢慢来 | 来源:发表于2019-08-09 15:26 被阅读0次

    路线绘制完毕的时候,想要截图,但是死活不能截取到完整的“起点”+“终点”图片,即使在截图之前将地图的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];
    }
    

    收获

    1. 使用百度地图绘制路线,可以使用模拟器来进行模拟人的走动,或者车跑,或者自定义位置。
      打开模拟器,去到导航栏,点击Debug,如下图,


      模拟器模拟运动
    2. 我写了NSMutableArray *overlays和annotations来存储添加的层和线,原来mapview自己会保存,删除的时候使用这个就OK了。

            [self.mapView removeOverlays:self.mapView.overlays];
            [self.mapView removeAnnotations:self.mapView.annotations];
    

    感谢

    https://www.jianshu.com/p/ae94bfd7da3a

    相关文章

      网友评论

          本文标题:iOS使用百度地图绘制轨迹遇到的坑

          本文链接:https://www.haomeiwen.com/subject/svlhjctx.html