美文网首页
地图之简单认识相关类及方法

地图之简单认识相关类及方法

作者: Kevin_wzx | 来源:发表于2022-07-21 10:35 被阅读0次

    目录

    百度地图相关类及方法
    1.基础创建及相关使用类
    2.发起导航算路(即开始导航)、导航中改变终点重新导航
    3.移除和添加地图的标注、移除地图覆盖物(包折线)
    4.发起路线规划、路线规划结果
    5.画折线(途经点)
    6.地图定位图标
    7.逆编码
    8.引入相关地图文件名和协议

    高德地图相关类及方法
    1.基础创建及相关使用类
    2.发起导航算路(即开始导航)、导航中改变终点重新导航
    3.移除和添加地图的标注、移除地图覆盖物(包折线)
    4.发起路线规划、路线规划结果
    5.画折线(起终点-骑行例子)
    6.地图定位图标
    7.逆编码
    8.引入相关地图文件名和协议

    地图SDK导入工程及plist权限添加

    1.百度地图相关类及方法

    1.基础创建及相关使用类
    创建地图、当前位置对象、定位管理类

    //初始化地图
    - (void)initMap {
        self.mapView = [[BMKMapView alloc] initWithFrame:CGRectZero];
        [self.view addSubview:self.mapView];
        [self.mapView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.view);
        }];
        self.mapView.delegate = self;
        self.mapZoomLevel = 15;//地图缩放级别
        [self.mapView setZoomLevel:self.mapZoomLevel];//级别,3-19
        self.mapView.overlookEnabled = NO;// 设定地图View能否支持俯仰角
        self.mapView.rotateEnabled = NO;//设定地图View能否支持旋转
        [self.locationManager startUpdatingLocation];//开始连续定位
        [self.locationManager startUpdatingHeading];//开始获取设备朝向(GPS)
        self.mapView.showsUserLocation = YES;//设定是否显示定位图层
        self.mapView.userTrackingMode = BMKUserTrackingModeHeading;//普通定位模式
        //定位图层自定义样式参数
        self.param = [[BMKLocationViewDisplayParam alloc] init];
        self.param.isAccuracyCircleShow = NO;//是否显示精度圈
        self.param.canShowCallOut = NO;//是否显示气泡
        self.param.locationViewImage = [UIImage imageNamed:@"bbx_carLocation"];//定位图标名称
        [self.mapView updateLocationViewWithParam:self.param];//动态定制我的位置样式
    }
    
    //司机当前位置对象
    - (BMKUserLocation *)userLocation {
        if (!_userLocation) {
            //初始化BMKUserLocation类的实例
            _userLocation = [[BMKUserLocation alloc] init];
        }
        return _userLocation;
    }
    
    //负责获取定位
    - (BMKLocationManager *)locationManager {
        if (!_locationManager) {
            //初始化BMKLocationManager类的实例
            _locationManager = [[BMKLocationManager alloc] init];
            //设置定位管理类实例的代理
            _locationManager.delegate = self;
            //设定定位坐标系类型,默认为 BMKLocationCoordinateTypeGCJ02
            _locationManager.coordinateType = BMKLocationCoordinateTypeBMK09LL;
            //设定定位精度,默认为 kCLLocationAccuracyBest
            _locationManager.desiredAccuracy = kCLLocationAccuracyBest;
            //设定定位类型,默认为 CLActivityTypeAutomotiveNavigation
            _locationManager.activityType = CLActivityTypeAutomotiveNavigation;
            //指定定位是否会被系统自动暂停,默认为NO
            _locationManager.pausesLocationUpdatesAutomatically = NO;
            /**
             是否允许后台定位,默认为NO。只在iOS 9.0及之后起作用。
             设置为YES的时候必须保证 Background Modes 中的 Location updates 处于选中状态,否则会抛出异常。
             由于iOS系统限制,需要在定位未开始之前或定位停止之后,修改该属性的值才会有效果。
             */
            _locationManager.allowsBackgroundLocationUpdates = NO;
            /**
             指定单次定位超时时间,默认为10s,最小值是2s。注意单次定位请求前设置。
             注意: 单次定位超时时间从确定了定位权限(非kCLAuthorizationStatusNotDetermined状态)
             后开始计算。
             */
            _locationManager.locationTimeout = 10;
        }
        return _locationManager;
    }
    
    //路线规划
    - (BMKRouteSearch *)routeSearch {
        if (!_routeSearch) {
            _routeSearch = [[BMKRouteSearch alloc] init];
            _routeSearch.delegate = self;
        }
        return _routeSearch;
    }
    

    地图定位代理方法

    /**
     * @brief 该方法为BMKLocationManager提供设备朝向的回调方法。
     * @param manager 提供该定位结果的BMKLocationManager类的实例
     * @param heading 设备的朝向结果
     */
    - (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager
              didUpdateHeading:(CLHeading * _Nullable)heading;
    
    /**
     *  @brief 连续定位回调函数。
     *  @param manager 定位 BMKLocationManager 类。
     *  @param location 定位结果,参考BMKLocation。
     *  @param error 错误信息。
     */
    - (void)BMKLocationManager:(BMKLocationManager * _Nonnull)manager didUpdateLocation:(BMKLocation * _Nullable)location orError:(NSError * _Nullable)error;
    

    地图代理方法

    /**
     *地图初始化完毕时会调用此接口
     *@param mapView 地图View
     */
    - (void)mapViewDidFinishLoading:(BMKMapView *)mapView;
    
    /**
     *地图区域改变完成后会调用此接口
     *@param mapView 地图View
     *@param animated 是否动画
     *@param reason 地区区域改变的原因
     */
    - (void)mapView:(BMKMapView *)mapView regionDidChangeAnimated:(BOOL)animated reason:(BMKRegionChangeReason)reason;
    
    /**
     *根据anntation生成对应的View
     *@param mapView 地图View
     *@param annotation 指定的标注
     *@return 生成的标注View
     */
    - (BMKAnnotationView *)mapView:(BMKMapView *)mapView viewForAnnotation:(id <BMKAnnotation>)annotation;
    
    /**
     *当点击annotation view弹出的泡泡时,调用此接口
     *@param mapView 地图View
     *@param view 泡泡所属的annotation view
     */
    - (void)mapView:(BMKMapView *)mapView annotationViewForBubble:(BMKAnnotationView *)view;
    
    /**
     *当选中一个annotation views时,调用此接口
     *当BMKAnnotation的title为nil,BMKAnnotationView的canShowCallout为NO时,不显示气泡,点击BMKAnnotationView会回调此接口。
     *当气泡已经弹出,点击BMKAnnotationView不会继续回调此接口。
     *@param mapView 地图View
     *@param view 选中的annotation views
     */
    - (void)mapView:(BMKMapView *)mapView didSelectAnnotationView:(BMKAnnotationView *)view;
    
    /**
     *点中底图空白处会回调此接口
     *@param mapView 地图View
     *@param coordinate 空白处坐标点的经纬度
     */
    - (void)mapView:(BMKMapView *)mapView onClickedMapBlank:(CLLocationCoordinate2D)coordinate;
    
    viewForAnnotation方法中自定义气泡view可以设置的一些属性

    2.发起导航算路(即开始导航)

    /**
     *  发起算路
     *
     *  @param eMode     算路方式,定义见BNRoutePlanMode
     *  @param naviNodes 算路节点数组,起点、途经点、终点按顺序排列,节点信息为BNRoutePlanNode结构
     *  @param naviTime  发起算路时间,用于优化算路结果,可以为nil
     *  @param delegate  算路委托,用于回调
     *  @param userInfo  用户需要传入的参数,货车导航算路需要传入BNaviTripTypeKey,值为BN_NaviTypeTruck
     */
    - (void)startNaviRoutePlan:(BNRoutePlanMode)eMode
                    naviNodes:(NSArray*)naviNodes
                         time:(BNaviCalcRouteTime*)naviTime
                     delegete:(id<BNNaviRoutePlanDelegate>)delegate
                     userInfo:(NSDictionary*)userInfo;
    

    导航中改变终点重新导航

    /**
     *  导航中改变终点
     *
     *  @param endNode  要切换的终点
     */
    - (void)resetNaviEndPoint:(BNRoutePlanNode *)endNode;
    

    3.移除和添加地图的标注

    [self.mapView removeAnnotations:self.mapView.annotations];//要移除的标注数组
    [self.mapView addAnnotations:clusters];//将一组标注添加到当前地图View中
    

    移除地图覆盖物(包折线)

    NSArray *allOverlays = self.mapView.overlays;
    [self.mapView removeOverlays:allOverlays];
    

    4.发起路线规划

    /**
     *驾乘路线检索
     *异步函数,返回结果在BMKRouteSearchDelegate的onGetDrivingRouteResult通知
     *@param drivingRoutePlanOption 驾车检索信息类
     *@return 成功返回YES,否则返回NO
     */
    - (BOOL)drivingSearch:(BMKDrivingRoutePlanOption *)drivingRoutePlanOption;
    
    /**
     *骑行路线检索
     *异步函数,返回结果在BMKRouteSearchDelegate的onGetRidingRouteResult通知
     *@param ridingRoutePlanOption 骑行检索信息类
     *@return 成功返回YES,否则返回NO
     */
    - (BOOL)ridingSearch:(BMKRidingRoutePlanOption *)ridingRoutePlanOption;
    
    #para mark -- 举例:
    //初始化司机路径规划
    - (void)creatPlan:(OrderListModel *)model {
        
        //起点(司机位置)
        BMKPlanNode *start = [[BMKPlanNode alloc] init];
        CLLocationCoordinate2D coordinate1;
        coordinate1.latitude = [LocationManager shareManager].location.coordinate.latitude;
        coordinate1.longitude = [LocationManager shareManager].location.coordinate.longitude;
        start.pt = coordinate1;
        //终点
        BMKPlanNode *end = [[BMKPlanNode alloc] init];
        CLLocationCoordinate2D coordinate;
        coordinate.latitude = model.start_lat;
        coordinate.longitude = model.start_lng;
        end.pt = model.startLocation.coordinate;
        //开车路线规划
        BMKDrivingRoutePlanOption * drivingRoutePlanOption= [[BMKDrivingRoutePlanOption alloc] init];
        drivingRoutePlanOption.from = start;
        drivingRoutePlanOption.to = end;
        drivingRoutePlanOption.drivingPolicy = BMK_DRIVING_DIS_FIRST;//传一个想要的规划策略给百度(最短距离,BMK_DRIVING_DIS_FIRST:1;百度默认0为时间最短)
        
        //节点数组
        NSMutableArray *nodesArray = [[NSMutableArray alloc]initWithCapacity:1];
        BMKPlanNode *startNode = [[BMKPlanNode alloc] init];
        startNode.pt = CLLocationCoordinate2DMake(model.start_lat, model.start_lng);
        startNode.name = @"fromeTip";
        [nodesArray addObject:startNode];
        drivingRoutePlanOption.wayPointsArray = nodesArray;
        
        //发起路线规划
        BOOL flag = [self.routeSearch drivingSearch:drivingRoutePlanOption];
        if (!flag){
            [SKToast showWithText:@"驾车路线规划检索发送失败"];
        } else {
            [SKToast showWithText:@"成功"];
        }
    }
    

    路线规划结果

    /**
     *返回驾乘搜索结果
     *@param searcher 搜索对象
     *@param result 搜索结果,类型为BMKDrivingRouteResult
     *@param error 错误号,@see BMKSearchErrorCode
     */
    - (void)onGetDrivingRouteResult:(BMKRouteSearch *)searcher result:(BMKDrivingRouteResult *)result errorCode:(BMKSearchErrorCode)error;
    
    /**
     *返回骑行搜索结果
     *@param searcher 搜索对象
     *@param result 搜索结果,类型为BMKRidingRouteResult
     *@param error 错误号,@see BMKSearchErrorCode
     */
    - (void)onGetRidingRouteResult:(BMKRouteSearch *)searcher result:(BMKRidingRouteResult *)result errorCode:(BMKSearchErrorCode)error;
    

    5.画折线(途经点)

    相关链接:
    https://www.jianshu.com/p/ce02bc7d9805
    https://www.jianshu.com/p/caf2e185462c

    //初始化司机路径规划
    - (void)creatPlan:(OrderListModel *)model {
        
        //起点(司机位置)
        BMKPlanNode* start = [[BMKPlanNode alloc] init];
        CLLocationCoordinate2D coordinate1;
        coordinate1.latitude = [LocationManager shareManager].location.coordinate.latitude;
        coordinate1.longitude = [LocationManager shareManager].location.coordinate.longitude;
        start.pt = coordinate1;
        BMKPlanNode* end = [[BMKPlanNode alloc] init];
        CLLocationCoordinate2D coordinate;
        if ([BBXDiaoduSortArrayManager shareManager].openDiaoduArray.count>0) {//智能调度
    
            NSMutableArray *temArray = [NSMutableArray array];
            temArray = [BBXDiaoduSortArrayManager shareManager].pickArray;
            OrderListModel *lastModel = temArray.lastObject;
            end.pt = lastModel.startLocation.coordinate;
            //end.pt = diaoduChuEndCoor;
            BMKDrivingRoutePlanOption * drivingRoutePlanOption= [[BMKDrivingRoutePlanOption alloc] init];//开车路线规划
            drivingRoutePlanOption.from = start;
            drivingRoutePlanOption.to = end;
            drivingRoutePlanOption.drivingPolicy = BMK_DRIVING_DIS_FIRST;//传一个想要的规划策略给百度(最短距离,BMK_DRIVING_DIS_FIRST:1;百度默认0为时间最短)
            
            //途径点坐标数组
            NSMutableArray <BMKPlanNode *> *wayPointsArray = [[NSMutableArray alloc]init];
            [temArray enumerateObjectsUsingBlock:^(OrderListModel * _Nonnull listModel, NSUInteger idx, BOOL * _Nonnull stop) {
                //数据源中最后一个元素作为终点,不加入途径点数组
                if(idx != temArray.count - 1){//&& idx!=0 奔溃
                    CLLocationCoordinate2D coor;
                    coor.latitude = listModel.start_lat;
                    coor.longitude = listModel.start_lng;
                    BMKPlanNode *after = [[BMKPlanNode alloc]init];
                    after.pt = coor;
                    [wayPointsArray addObject:after];
                }
            }];
            drivingRoutePlanOption.wayPointsArray = wayPointsArray;
            BOOL flag = [self.routeSearch drivingSearch:drivingRoutePlanOption];
            if (!flag){
                [SKToast showWithText:@"驾车路线规划检索发送失败"];
            } else {
                [SKToast showWithText:@"成功"];
            }
        }
    }
    
    //路径规划结果回调方法
    #pragma mark -- 路径规划
    /**
     *返回驾车的路线绘制搜索结果
     *@param searcher 搜索对象
     *@param result 搜索结果,类型为BMKDrivingRouteResult
     *@param error 错误号,@see BMKSearchErrorCode
     */
    - (void)onGetDrivingRouteResult:(BMKRouteSearch*)searcher result:(BMKDrivingRouteResult*)result errorCode:(BMKSearchErrorCode)error {
            
        if (error == BMK_SEARCH_ST_EN_TOO_NEAR) {//起点,终点距离太近
            [SKToast showWithText:@"距离太近,无法规划路线"];
        } else {
            
            //检索结果正常返回、其他规划错误
            if ([searcher isEqual:self.routeSearch]) {
                if (self.ailistArray.count>0) {//智能调度
                    //规划线路
                    //1.坐标点的个数
                    __block NSUInteger pointCount = 0;
                    BMKDrivingRouteLine *routeline = (BMKDrivingRouteLine *)result.routes.firstObject;//获取所有驾车路线中第一条路线
                    [routeline.steps enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        BMKDrivingStep *step = routeline.steps[idx];
                        pointCount += step.pointsCount;//遍历所有路段统计路段所经过的地理坐标集合内点的个数
                    }];
    
                    //2.指定的直角坐标点数组
                    BMKMapPoint *points = new BMKMapPoint[pointCount];
                    __block NSUInteger j = 0;
                    [routeline.steps enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
                        BMKDrivingStep *step = routeline.steps[idx];
                        for (NSUInteger i = 0; i < step.pointsCount; i ++) {
                            points[j].x = step.points[i].x;//将每条路段所经过的地理坐标点赋值
                            points[j].y = step.points[i].y;
                            j ++;
                        }
                    }];
    
                    //3.根据指定直角坐标点生成一段折线
                    self.polyline = [BMKPolyline polylineWithPoints:points count:pointCount];
                    [self.mapView addOverlay:self.polyline];
                    [self mapViewFitPolyline:self.polyline withMapView:self.mapView];//根据polyline设置地图范围
                }
            }
        }
    }
    
    //根据polyline设置地图范围
    - (void)mapViewFitPolyline:(BMKPolyline *) polyLine withMapView:(BMKMapView *)mapView {
        CGFloat leftTopX, leftTopY, rightBottomX, rightBottomY;
        if (polyLine.pointCount < 1) {
            return;
        }
        BMKMapPoint pt = polyLine.points[0];
        // 左上角顶点
        leftTopX = pt.x;
        leftTopY = pt.y;
        // 右下角顶点
        rightBottomX = pt.x;
        rightBottomY = pt.y;
        for (int i = 1; i < polyLine.pointCount; i++) {
            BMKMapPoint pt = polyLine.points[i];
            leftTopX = pt.x < leftTopX ? pt.x : leftTopX;
            leftTopY = pt.y < leftTopY ? pt.y : leftTopY;
            rightBottomX = pt.x > rightBottomX ? pt.x : rightBottomX;
            rightBottomY = pt.y > rightBottomY ? pt.y : rightBottomY;
        }
        
        BMKMapRect rect;
        rect.origin = BMKMapPointMake(leftTopX, leftTopY);
        rect.size = BMKMapSizeMake(rightBottomX - leftTopX, rightBottomY - leftTopY);
        UIEdgeInsets padding = UIEdgeInsetsMake(100, 100, 100, 100);//这个自己根据需求调整
        BMKMapRect fitRect = [self.mapView mapRectThatFits:rect edgePadding:padding];
        [self.mapView setVisibleMapRect:fitRect];
    }
    
    //设置路线规划折线的样式
    - (BMKOverlayView *)mapView:(BMKMapView *)mapView viewForOverlay:(id<BMKOverlay>)overlay {
        if ([overlay isKindOfClass:[BMKPolyline class]]) {
            BMKPolylineView* polylineView = [[BMKPolylineView alloc] initWithOverlay:overlay];
            polylineView.strokeColor = [UIColor colorWithRed:51/255.0 green:149/255.0 blue:255/255.0 alpha:1.0];//折线颜色
            polylineView.lineWidth = 6.0; //折线宽度
            return polylineView;
        }
        return nil;
    }
    

    6.地图定位图标

    @property (nonatomic, strong) BMKLocationViewDisplayParam *param;//定位图层图标
    
    //初始化地图
    - (void)initMap {
        self.mapView = [[BMKMapView alloc] init];//WithFrame:CGRectZero];
        
        self.mapView.delegate = self;
        self.mapZoomLevel = 15;//地图缩放级别
        [self.mapView setZoomLevel:self.mapZoomLevel];//级别,3-19
        [self.view addSubview:self.mapView];
        self.mapView.overlookEnabled = NO;
        [self.mapView mas_makeConstraints:^(MASConstraintMaker *make) {
            make.edges.equalTo(self.view);
        }];
        [self.locationManager startUpdatingLocation];//开始连续定位
        [self.locationManager startUpdatingHeading];//开始获取设备朝向(GPS)
        self.mapView.showsUserLocation = YES;//设定是否显示定位图层
        self.mapView.userTrackingMode = BMKUserTrackingModeHeading;//普通定位模式
        
        //定位图层自定义样式参数
        self.param = [[BMKLocationViewDisplayParam alloc] init];
        self.param.isAccuracyCircleShow = NO;//是否显示精度圈
        self.param.canShowCallOut = NO;//是否显示气泡
        self.param.locationViewImage = [UIImage imageNamed:@"bbx_carLocation"];//定位图标名称
        self.mapView.rotateEnabled = NO;//设定地图View能否支持旋转
        self.param.locationViewHierarchy = LOCATION_VIEW_HIERARCHY_TOP;
        self.param.locationViewOffsetY = 0;//定位图标Y轴偏移量(屏幕坐标)
        [self.mapView updateLocationViewWithParam:self.param];//动态定制我的位置样式
    }
    
    //其他地方有区别更新
    - (void)updateParam {
        //代驾有单且未上车的时候设置定位图标
        if ([BBXDriverInfo shareManager].driverServiceSceneMode == 1) {//代驾
            if (self.orderArray) {
                NSArray *tempArray = [NSArray arrayWithArray:self.orderArray];
                for (OrderListModel *model in tempArray) {
                    if (model.order_status == Order_state_sended) {
                        self.param.locationViewImage = [UIImage imageNamed:@"icon_map_designatedDriver"];//有单且未上车
                    }
                }
            }
        } else {
            self.param.locationViewImage = [UIImage imageNamed:@"bbx_carLocation"];//定位图标名称
        }
        [self.mapView updateLocationViewWithParam:self.param];//动态定制我的位置样式
    }
    
    #para mark -- 实现该方法,否则定位图标不出现
    //连续定位回调方法(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 ([BBXDiaoduSortArrayManager shareManager].openDiaoduArray.count>0) {//智能调度
    //        没有添加当前位置导致定位图标不出现
    //    } else {
            self.userLocation.location = location.location;//司机当前位置信息
            [self.mapView updateLocationData:self.userLocation];//实现该方法,否则定位图标不出现
    //    }
    }
    

    7.逆编码

    相关链接:
    https://blog.csdn.net/wjchao1990/article/details/51727669
    https://xiaozhuanlan.com/topic/4968730251
    https://blog.csdn.net/nameis2541748437/article/details/49766105
    https://www.cnblogs.com/guitarandcode/p/5783805.html(CLPlacemark属性)

    //定位按钮
    - (void)locationButtonAction {
        self.mapView.centerCoordinate = self.userLocation.location.coordinate;
        [self.mapView setZoomLevel:18];
        BMKReverseGeoCodeSearchOption *reverseGeoCodeOption = [[BMKReverseGeoCodeSearchOption alloc]init];
        reverseGeoCodeOption.location = self.userLocation.location.coordinate;
        reverseGeoCodeOption.isLatestAdmin = YES;
        //发起逆编码请求
        BOOL flag = [self.search reverseGeoCode: reverseGeoCodeOption];
        if (flag) {
            NSLog(@"逆geo检索发送成功");
        }  else  {
            NSLog(@"逆geo检索发送失败");
        }
    }
    
    //逆编码结果
    - (void)onGetReverseGeoCodeResult:(BMKGeoCodeSearch *)searcher result:(BMKReverseGeoCodeSearchResult *)result errorCode:(BMKSearchErrorCode)error {
        
        if (error == BMK_SEARCH_NO_ERROR) {
            if (searcher == self.search) {
                self.adCode = result.addressDetail.adCode;
                NSLog(@"速递-adCode返回结果:%@",self.adCode);
            } else if (searcher == self.searchTwo) {
                self.adCodeTwo = result.addressDetail.adCode;
                NSLog(@"速递-adCodeTwo返回结果:%@",self.adCodeTwo);
            }
        } else {
            NSLog(@"速递-检索失败");
        }
    }
    

    8.引入相关地图文件名和协议

    文件名:
    #import <BaiduMapAPI_Map/BMKMapView.h>
    #import <BaiduMapAPI_Map/BMKMapComponent.h>
    #import <BaiduMapAPI_Utils/BMKGeometry.h>
    #import <BaiduMapAPI_Base/BMKBaseComponent.h>
    #import <BaiduMapAPI_Search/BMKSearchComponent.h>
    
    协议:
    <BMKMapViewDelegate,BMKRouteSearchDelegate, BNNaviUIManagerDelegate,BMKLocationManagerDelegate,BNNaviRoutePlanDelegate>
    

    2.高德地图相关类及方法

    1.基础创建及相关使用类
    创建地图、当前位置对象、定位管理类

    //初始化地图
    - (void)initMap {
        self.mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:self.mapView];
        self.mapView.delegate = self;
        self.mapView.showsUserLocation = YES;
        self.mapView.zoomLevel = 15;//地图缩放级别
        self.mapView.userTrackingMode = MAUserTrackingModeFollow;//定位用户位置的模式
        self.mapView.rotateEnabled = NO;//是否支持旋转
        self.mapView.rotateCameraEnabled = NO;
        
        [self.locationManager startUpdatingLocation];//连续定位回调方法(location定位结果)
        [self.locationManager startUpdatingHeading];//设备朝向回调方法;如果设备支持方向识别,则会通过代理回调方法
        
        //定位图层图标
        self.represent = [[MAUserLocationRepresentation alloc] init];
        self.represent.showsAccuracyRing = NO;//精度圈是否显示
        self.represent.image = kImage(@"bbx_carLocation");
        [self.mapView updateUserLocationRepresentation:self.represent];
    }
    
    //司机当前位置对象
    - (MAUserLocation *)userLocation {
        if (!_userLocation) {
            _userLocation = [[MAUserLocation alloc] init];
        }
        return _userLocation;
    }
    
    //定位管理类
    - (AMapLocationManager *)locationManager {
        if (!_locationManager) {
            _locationManager = [[AMapLocationManager alloc] init];
            _locationManager.delegate = self;
            [_locationManager setPausesLocationUpdatesAutomatically:NO];
            [_locationManager setAllowsBackgroundLocationUpdates:NO];
        }
        return _locationManager;
    }
    
    //路线规划
    - (AMapSearchAPI *)mapSearch {
        if (!_mapSearch) {
            _mapSearch = [[AMapSearchAPI alloc] init];
            _mapSearch.delegate = self;
        }
        return _mapSearch;
    }
    

    地图定位代理方法

    /**
     *  @brief 设备方向改变时回调函数
     *  @param manager 定位 AMapLocationManager 类。
     *  @param newHeading 设备朝向。
     */
    - (void)amapLocationManager:(AMapLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading;
    
    /**
     *  @brief 连续定位回调函数.注意:如果实现了本方法,则定位信息不会通过amapLocationManager:didUpdateLocation:方法回调。
     *  @param manager 定位 AMapLocationManager 类。
     *  @param location 定位结果。
     *  @param reGeocode 逆地理信息。
     */
    - (void)amapLocationManager:(AMapLocationManager *)manager didUpdateLocation:(CLLocation *)location reGeocode:(AMapLocationReGeocode *)reGeocode;
    
    /**
     * @brief 当前位置更新回调(无论是否在导航中,只要当前位置有更新就会回调)
     * @param compositeManager 导航组件类
     * @param naviLocation 当前位置信息,参考 AMapNaviLocation 类
     */
    //用户位置更新后,会调用此函数(userLocation 新的用户位置)
    - (void)compositeManager:(AMapNaviCompositeManager *_Nonnull)compositeManager updateNaviLocation:(AMapNaviLocation *_Nullable)naviLocation;
    

    地图代理方法

    /**
     * @brief 地图加载成功
     * @param mapView 地图View
     */
    - (void)mapViewDidFinishLoadingMap:(MAMapView *)mapView;
    
    /**
     * @brief 地图区域改变完成后会调用此接口,如实现此接口则不会触发回掉mapView:regionDidChangeAnimated:
     * @param mapView 地图View
     * @param animated 是否动画
     * @param wasUserAction 标识是否是用户动作
     */
    - (void)mapView:(MAMapView *)mapView regionDidChangeAnimated:(BOOL)animated wasUserAction:(BOOL)wasUserAction;
    
     * @param mapView 地图View
     * @param annotation 指定的标注
     * @return 生成的标注View
     */
    - (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id <MAAnnotation>)annotation;
    
    /**
     * @brief 当选中一个annotation view时,调用此接口. 注意如果已经是选中状态,再次点击不会触发此回调。取消选中需调用-(void)deselectAnnotation:animated:
     * @param mapView 地图View
     * @param view 选中的annotation view
     */
    - (void)mapView:(MAMapView *)mapView didSelectAnnotationView:(MAAnnotationView *)view;
    
    /**
     * @brief 单击地图回调,返回经纬度
     * @param mapView 地图View
     * @param coordinate 经纬度
     */
    //点中地图空白处会回调
    - (void)mapView:(MAMapView *)mapView didSingleTappedAtCoordinate:(CLLocationCoordinate2D)coordinate;
    
    viewForAnnotation方法中自定义气泡view可以设置的一些属性

    2.发起导航算路(即开始导航)

    /**
     * @brief 驾车路径规划成功后的回调函数 since 6.1.0
     * @param driveManager 驾车导航管理类
     * @param type 路径规划类型,参考 AMapNaviRoutePlanType
     */
    - (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteSuccessWithType:(AMapNaviRoutePlanType)type;
    
    /**
     * @brief 开始实时导航. 注意:必须在路径规划成功的情况下,才能够开始实时导航
     * @return 是否成功
     */
    - (BOOL)startGPSNavi;
    
    #para mark -- 实际应用
    - (void)driveManager:(AMapNaviDriveManager *)driveManager onCalculateRouteSuccessWithType:(AMapNaviRoutePlanType)type {
        //算路成功后开始GPS导航
        [[AMapNaviDriveManager sharedInstance] startGPSNavi];
    }
    

    导航中改变终点重新导航

    //后期有需求应用再总结
    

    3.移除和添加地图的标注、移除地图覆盖物(包折线)

    [self.mapView removeAnnotations:[self.mapView annotations]];//要移除的标注数组
    [self.mapView addAnnotations:self.annotations];//向地图窗口添加一组标注
    

    移除地图覆盖物(包折线)

    NSArray *array = [NSArray arrayWithArray:self.mapView.overlays];
    [self.mapView removeOverlays:array];//移除遮盖物
    

    4.发起路线规划

    /**
     * @brief 驾车路径规划查询接口
     * @param request 查询选项。具体属性字段请参考 AMapDrivingRouteSearchRequest 类。
     */
    - (void)AMapDrivingRouteSearch:(AMapDrivingRouteSearchRequest *)request;
    
    /**
     * @brief 骑行路径规划查询接口 (since 4.3.0)
     * @param request 查询选项。具体属性字段请参考 AMapRidingRouteSearchRequest 类。
     */
    - (void)AMapRidingRouteSearch:(AMapRidingRouteSearchRequest *)request;
    
    #para mark -- 举例:
    //初始化司机路径规划
    - (void)creatPlan:(BBXOrderListModel *)model {
        
        //发起驾车路线规划
        AMapDrivingRouteSearchRequest *navi = [[AMapDrivingRouteSearchRequest alloc] init];
        AMapGeoPoint *endPoint;
        navi.origin = [AMapGeoPoint locationWithLatitude:BBXLocationManager.shareManager.location.coordinate.latitude longitude:BBXLocationManager.shareManager.location.coordinate.longitude];//起点(司机位置)
        CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:model.end_lat longitude:model.end_lng];
        CLLocationDegrees lat = listLocation.coordinate.latitude;
        CLLocationDegrees lng = listLocation.coordinate.longitude;
        endPoint = [AMapGeoPoint locationWithLatitude:lat longitude:lng];
        navi.destination = endPoint;//终点(叫代驾或叫车的人的位置)
        navi.strategy = 2;//距离优先(传一个想要的规划策略给高德)
        [self.mapSearch AMapDrivingRouteSearch:navi];//发起驾车路径规划查询
    }
    

    路线规划结果

    /**
     * @brief 路径规划查询回调
     * @param request  发起的请求,具体字段参考 AMapRouteSearchBaseRequest 及其子类。
     * @param response 响应结果,具体字段参考 AMapRouteSearchResponse 。
     */
    - (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response;
    
    #para mark -- 哪种路径规划设置
    默认是驾车路径,可以通过判断request设置,比如骑行 AMapRidingRouteSearchRequest,驾车 AMapDrivingRouteSearchRequest
    

    5.画折线(起终点-骑行例子)

    相关链接:
    https://lbs.amap.com/api/ios-sdk/guide/draw-on-map/draw-polyline
    https://www.jianshu.com/p/79b455c74679

    //发起骑行路线规划
    - (void)updateViewByShowingOrderListModel:(BBXOrderListModel *)orderListModel {
    
        //发起骑行路线规划
        AMapRidingRouteSearchRequest *navi = [[AMapRidingRouteSearchRequest alloc] init];
        AMapGeoPoint *endPoint;
        navi.origin = [AMapGeoPoint locationWithLatitude:BBXLocationManager.shareManager.location.coordinate.latitude longitude:BBXLocationManager.shareManager.location.coordinate.longitude];//起点
        CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
        CLLocationDegrees lat = listLocation.coordinate.latitude;
        CLLocationDegrees lng = listLocation.coordinate.longitude;
        endPoint = [AMapGeoPoint locationWithLatitude:lat longitude:lng];
        navi.destination = endPoint;//终点(叫代驾或叫车的人的位置)
        navi.type = 1;//推荐路线
        [self.mapSearch AMapRidingRouteSearch:navi];//发起骑行路径规划查询
    }
    
    #para mark -- 途经点相关
    //途经点 AMapGeoPoint 数组,目前最多支持6个途经点
    @property (nonatomic, copy) NSArray<AMapGeoPoint *> *waypoints;
    
    #pragma mark -- 高德路线规划
    //骑行路线规划结果
    - (void)onRouteSearchDone:(AMapRouteSearchBaseRequest *)request response:(AMapRouteSearchResponse *)response {
        
        NSArray *array = [NSArray arrayWithArray:self.mapView.annotations];
        [self.mapView removeAnnotations:array];
        array = [NSArray arrayWithArray:self.mapView.overlays];
        [self.mapView removeOverlays:array];//移除遮盖物
        
        if (response.route == nil) {//路线规划出错(太近检索失败)
    
            AMapRoute *route = response.route;
            AMapPath *path = [route.paths firstObject];
    
            //添加起点标注
            BBXPassAnnotation *startAnnotation = [[BBXPassAnnotation alloc] init];
            startAnnotation.type = @"start";
            CLLocation * driverLocation = [BBXLocationManager shareManager].location;
            startAnnotation.coordinate = driverLocation.coordinate;
            [self.mapView addAnnotation:startAnnotation];
    
            //添加终点标注
            BBXPassAnnotation  *endAnnotation = [[BBXPassAnnotation alloc] init];
            endAnnotation.type = @"end";
            CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
            endAnnotation.coordinate = listLocation.coordinate;
            [self.mapView addAnnotation:endAnnotation];
    
            //泡泡弹出的地点(叫代驾的人所在的点)
            BBXPassAnnotation *passAn = [[BBXPassAnnotation alloc] init];
            passAn.type = @"Pop";
            passAn.title = @"距离车主1.0米";
            CLLocation *palocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
            passAn.coordinate = palocation.coordinate;
            [self.mapView addAnnotation:passAn];
            
            //画路线规划的折线
            MAPolyline *polyline = [self polylinesForPath:path];//轨迹点
            [self.mapView addOverlay:polyline];//画路线规划的折线
            [self mapViewFitPolyLine:polyline];//根据polyline设置地图范围
            return;
        } else {
            
            AMapPath *path = [response.route.paths firstObject];
            NSInteger mile = path.distance;
            if (mile>=0 && mile<=100.0) {//100米认为比较近
                [BBXProgressHUD showInfo:@"距离太近,无法规划路线"];
                return;
            }
            //路线规划成功
            if ([request isKindOfClass:[AMapRidingRouteSearchRequest class]]) {//骑行路径规划
                
                AMapRoute *route = response.route;
                AMapPath *path = [route.paths firstObject];
                NSInteger size = [path.steps count];
               
                for (int i = 0; i < size; i++) {
                                    
                    if (i == 0) {
                        //添加起点标注
                        BBXPassAnnotation *startAnnotation = [[BBXPassAnnotation alloc] init];
                        startAnnotation.type = @"start";
                        CLLocation *startLocat = [[CLLocation alloc] initWithLatitude:route.origin.latitude longitude:route.origin.longitude];
                        startAnnotation.coordinate = startLocat.coordinate;
                        [self.mapView addAnnotation:startAnnotation];
                    }
    
                    if(i == size-1) {
                        //添加终点标注
                        BBXPassAnnotation *endAnnotation = [[BBXPassAnnotation alloc] init];
                        endAnnotation.type = @"end";
                        CLLocation *endLocat = [[CLLocation alloc] initWithLatitude:route.destination.latitude longitude:route.destination.longitude];
                        endAnnotation.coordinate = endLocat.coordinate;
                        [self.mapView addAnnotation:endAnnotation];
                    }
                }
    
                //泡泡弹出的地点(叫代驾的人所在的点)
                BBXPassAnnotation *passAn = [[BBXPassAnnotation alloc] init];
                passAn.type = @"Pop";
                CLLocation *listLocation = [[CLLocation alloc] initWithLatitude:self.orderListModel.start_lat longitude:self.orderListModel.start_lng];
                passAn.coordinate = listLocation.coordinate;
                float distance = path.distance;
                if (distance >= 100.0) {
                    NSString *kmString = [BBXMileageConvert meterTurnKilometreOneDecimalWith:distance];//米转公里
                    passAn.title = [NSString stringWithFormat:@"距离车主%@公里", kmString];
                } else {
                    if (distance<=10.0) {
                        distance = 1.0;
                        passAn.title = [NSString stringWithFormat:@"距离车主%.1f米", distance];
                    } else {
                        passAn.title = [NSString stringWithFormat:@"距离车主%.1f米", distance];
                    }
                }
                [self.mapView addAnnotation:passAn];
    
                //画路线规划的折线
                MAPolyline *polyline = [self polylinesForPath:path];//轨迹点
                [self.mapView addOverlay:polyline];//画路线规划的折线
                [self mapViewFitPolyLine:polyline];//根据polyline设置地图范围
            }
        }
    }
    
    //路径规划检索失败
    - (void)AMapSearchRequest:(id)request didFailWithError:(NSError *)error {
        NSLog(@"Error: %@", error);
    }
    
    //路线解析-轨迹点
    - (MAPolyline *)polylinesForPath:(AMapPath *)path {
        if (path == nil || path.steps.count == 0){
            return nil;
        }
        NSMutableString *polylineMutableString = [@"" mutableCopy];
        for (AMapStep *step in path.steps) {
            [polylineMutableString appendFormat:@"%@;",step.polyline];
        }
        NSUInteger count = 0;
        CLLocationCoordinate2D *coordinates = [self coordinatesForString:polylineMutableString
                                                         coordinateCount:&count
                                                              parseToken:@";"];
        MAPolyline *polyline = [MAPolyline polylineWithCoordinates:coordinates count:count];
        free(coordinates), coordinates = NULL;
        return polyline;
    }
    
    //解析经纬度
    - (CLLocationCoordinate2D *)coordinatesForString:(NSString *)string
                                     coordinateCount:(NSUInteger *)coordinateCount
                                          parseToken:(NSString *)token{
        if (string == nil){
            return NULL;
        }
        
        if (token == nil){
            token = @",";
        }
        
        NSString *str = @"";
        if (![token isEqualToString:@","]) {
            str = [string stringByReplacingOccurrencesOfString:token withString:@","];
        } else {
            str = [NSString stringWithString:string];
        }
        
        NSArray *components = [str componentsSeparatedByString:@","];
        NSUInteger count = [components count] / 2;
        if (coordinateCount != NULL){
            *coordinateCount = count;
        }
        CLLocationCoordinate2D *coordinates = (CLLocationCoordinate2D*)malloc(count * sizeof(CLLocationCoordinate2D));
        
        for (int i = 0; i < count; i++){
            coordinates[i].longitude = [[components objectAtIndex:2 * i]     doubleValue];
            coordinates[i].latitude  = [[components objectAtIndex:2 * i + 1] doubleValue];
        }
        return coordinates;
    }
    
    //根据polyline设置地图范围
    - (void)mapViewFitPolyLine:(MAPolyline *) polyLine {
        CGFloat leftTopX, leftTopY, rightBottomX, rightBottomY;
        if (polyLine.pointCount < 1) {
            return;
        }
        MAMapPoint pt = polyLine.points[0];//BMKMapPoint
        // 左上角顶点
        leftTopX = pt.x;
        leftTopY = pt.y;
        // 右下角顶点
        rightBottomX = pt.x;
        rightBottomY = pt.y;
        for (int i = 1; i < polyLine.pointCount; i++) {
            MAMapPoint pt = polyLine.points[i];
            leftTopX = pt.x < leftTopX ? pt.x : leftTopX;
            leftTopY = pt.y < leftTopY ? pt.y : leftTopY;
            rightBottomX = pt.x > rightBottomX ? pt.x : rightBottomX;
            rightBottomY = pt.y > rightBottomY ? pt.y : rightBottomY;
        }
    
        MAMapRect rect;//BMKMapRect
        rect.origin = MAMapPointMake(leftTopX, leftTopY);//BMKMapPointMake
        rect.size = MAMapSizeMake(rightBottomX - leftTopX, rightBottomY - leftTopY);//BMKMapSizeMake
        UIEdgeInsets padding = UIEdgeInsetsMake(175, 175, 175, 175);//这个自己根据需求调整
        MAMapRect fitRect = [self.mapView mapRectThatFits:rect edgePadding:padding];
        [self.mapView setVisibleMapRect:fitRect];
    }
    
    //设置折线的样式
    - (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id<MAOverlay>)overlay {
        if ([overlay isKindOfClass:[MAPolyline class]]){
            MAPolylineRenderer *polylineView = [[MAPolylineRenderer alloc] initWithOverlay:overlay];//BMKPolylineView
            polylineView.strokeColor = [UIColor colorWithRed:51/255.0 green:149/255.0 blue:255/255.0 alpha:1.0];//折线颜色
            polylineView.lineWidth = 6.0; //折线宽度
            polylineView.lineJoinType = kMALineJoinRound;//连接类型
            return polylineView;//BMKOverlayView
        }
        return nil;
    }
    

    6.地图定位图标

    @property (nonatomic, strong) MAUserLocationRepresentation *represent;//定位图层图标
    
    //初始化地图
    - (void)initMap {
        self.mapView = [[MAMapView alloc] initWithFrame:self.view.bounds];
        [self.view addSubview:self.mapView];
        self.mapView.delegate = self;
        self.mapView.showsUserLocation = YES;
        self.mapView.zoomLevel = 15;//地图缩放级别
        self.mapView.userTrackingMode = MAUserTrackingModeFollow;//定位用户位置的模式
        self.mapView.rotateEnabled = NO;//是否支持旋转
        self.mapView.rotateCameraEnabled = NO;
        
        [self.locationManager startUpdatingLocation];//连续定位回调方法(location定位结果)
        [self.locationManager startUpdatingHeading];//设备朝向回调方法;如果设备支持方向识别,则会通过代理回调方法
        
        //定位图层图标
        self.represent = [[MAUserLocationRepresentation alloc] init];
        self.represent.showsAccuracyRing = NO;//精度圈是否显示
        self.represent.image = kImage(@"bbx_carLocation");
        [self.mapView updateUserLocationRepresentation:self.represent];
    }
    
    //其他地方有区别更新
    - (void)updateParam {
        //代驾有单且未上车的时候设置定位图标
        if ([BBXDriverInfo sharedInstance].driverServiceSceneMode == 1) {//代驾
            if (self.orderArray) {
                NSArray *tempArray = [NSArray arrayWithArray:self.orderArray];
                for (BBXOrderListModel *model in tempArray) {
                    if (model.order_status == Order_state_sended) {
                        self.represent.image = kImage(@"icon_map_designatedDriver");//有单且未上车
                    } else {
                        self.represent.image = kImage(@"bbx_carLocation");//定位图标名称
                    }
                }
            } else {
                self.represent.image = kImage(@"bbx_carLocation");//定位图标名称
            }
        } else {
            self.represent.image = kImage(@"bbx_carLocation");//定位图标名称
        }
        [self.mapView updateUserLocationRepresentation:self.represent];//动态定制我的位置样式
    }
    

    7.逆编码

    相关链接:https://blog.csdn.net/chongran9230/article/details/100804174

    8.引入相关地图文件名和协议

    文件名:
    #import <AMapNaviKit/AMapNaviKit.h>
    #import <AMapSearchKit/AMapSearchKit.h>
    #import <AMapFoundationKit/AMapFoundationKit.h>
    #import <AMapLocationKit/AMapLocationKit.h>
    
    协议:
    <MAMapViewDelegate, AMapSearchDelegate, AMapLocationManagerDelegate>
    

    3.地图SDK导入工程及plist权限添加

    百度地图相关SDK:地图、导航、定位、鹰眼 百度地图使用相关权限 高德地图相关SDK:地图、导航、定位、鹰眼 高德地图使用相关权限

    判断手机App地图定位权限是否有打开:

    举例:如果App定位权限不是“始终”,则提醒打开
    - (void)jugdeIsOpenAlwaysLocation {
        
        //如果用户选择的定位权限不是“始终”,则弹窗让用户修改权限
        if ([CLLocationManager authorizationStatus] != kCLAuthorizationStatusAuthorizedAlways) {
            UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"定位权限请选择“始终”,否则服务无法使用!" preferredStyle:UIAlertControllerStyleAlert];
            UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [self.navigationController popToRootViewControllerAnimated:YES];
            }];
            UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"前往开启" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
            }];
            [alertController addAction:cancelAction];
            [alertController addAction:okAction];
            [self presentViewController:alertController animated:YES completion:nil];
            return;
        }
    }
    

    相关文章

      网友评论

          本文标题:地图之简单认识相关类及方法

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