示例中心
功能在线体验
控制台

骑行路线规划

该示例将骑行路线规划方案以Overlay和列表两种方式显示。
00:00 / 01:00
扫描二维码在手机端体验功能
体验移动端 扫码体验移动端

示例特点

骑行方案的多种表现形式(地图形式和列表展示),同时将 RideRouteOverlay 开源,帮助您做自定义样式的显示方案。

用到产品

Android 地图 SDK

核心类/接口

接口

说明

版本

RouteSearch.RideRouteQuery

RideRouteQuery(RouteSearch.FromAndTo fromAndTo, int mode)

构造函数,构造骑行路线规划查询参数对象。

V3.5.0版本起

RouteSearch

calculateRideRoute(RouteSearch.RideRouteQuery rideQuery)

骑行路线规划异步接口。

V3.5.0版本起

RouteSearch.OnRouteSearchListener

onRideRouteSearched(RideRouteResult rideRouteResult, int errorCode)

骑行路径规划结果的回调方法。

V3.5.0版本起

RideRouteResult

getPaths()

返回骑行路径规划方案。

V3.5.0版本起

RidePath

getSteps()

返回骑行方案的路段列表。

V3.5.0版本起

RideStep

getBusLines()

返回此路段的公交导航信息。

V3.5.0版本起


getRoad()

返回骑行路段的道路名称。

V3.5.0版本起

核心难点

1、如何解析骑行规划的结果对象?

a)通过 RideRouteResult.getPaths() 方法获取全部的骑行路径规划方案的列表,列表中是 RidePath 对象。

b)RidePath 对象就是一个完整骑路线方案,每个方案都是由多个 RideStep 构成。

c)通过 RideStep 对象,可以通过 getPolyline() 方法获取这个 Step 的坐标点集合,用来在地图上绘制线路;也可以通过 getRoad() 方法获取骑行路段的道路名称。

2、如何更改显示在地图上的 RideRouteOverlay 的样式(如:起终点图标、线路的颜色、宽度等)?

在本示例中,RideRouteOverlay 已对所有开发者开源,您可以参考源码修改 Overlay 的样式,其中:

 

  • 修改 getStartBitmapDescriptor() 方法的返回值,可以修改起点的图标。
  • 修改 getRideColor() 方法的返回值,可以修改骑行路线的颜色。
00:00 / 01:00
扫描二维码在手机端体验功能
体验移动端 扫码体验移动端

示例特点

将规划出来的骑行路线以 Overlay 显示在地图上,同时也以列表展示路线详情。

用到产品

iOS 地图 SDK

核心类/接口

接口

说明

版本

MAMapView

addOverlay:

向地图窗口添加Overlay。

V2.0.0版本起


addAnnotation:

向地图窗口添加标注。

V2.0.0版本起

MAMapViewDelegate

mapView:viewForAnnotation:

地图上的起始点,终点,拐点的标注的回调,可以自定义图标展示等。

V2.0.0版本起


mapView:rendererForOverlay:

地图上覆盖物的渲染的回调,可以设置路径线路的宽度,颜色等。

V3.0.0版本起

AMapSearchAPI

AMapRidingRouteSearch:

骑行路径规划查询接口。

V4.3.0版本起

AMapRidingRouteSearchRequest

type

路径方案类型([default = 0])0-推荐路线及最快路线综合, 1-推荐路线, 2-最快路线 。

V4.3.0版本起

AMapRouteSearchBaseRequest

origin

出发点坐标。

V3.0.0版本起


destination

目的地坐标。

V3.0.0版本起

AMapSearchDelegate

onRouteSearchDone:response:

路径规划查询完成回调。

V3.0.0版本起

核心难点

1、如何解析骑行规划结果对象。

a)通过 response.route.paths 可以获取到 AMapPath 列表。

b)AMapPath 对象就是一条骑行路线方案,每个方案都是由多个 AMapStep 构成。

c)可以通过 AMapStep.polyline 属性获取这个路段的坐标点,用于绘制路线;也可通过 AMapStep.road 属性获取该导航路段的名称。

在本示例中,MANaviRoute 是一个生成路线 Polyline 和起终点以及中间节点的 Annotaion 的工具类,省去了您去解析 response 对象的成本。

//在地图上显示当前选择的路径
- (void)presentCurrentRouteCourse {

    if (self.totalRouteNums <= 0) {
        return;
    }

    [self.naviRoute removeFromMapView];  //清空地图上已有的路线

    self.infoLabel.text = [NSString stringWithFormat:@"共%u条路线,当前显示第%u条",(unsigned)self.totalRouteNums,(unsigned)self.currentRouteIndex + 1];  //提示信息

    MANaviAnnotationType type = MANaviAnnotationTypeRiding; //骑行类型

    AMapGeoPoint *startPoint = [AMapGeoPoint locationWithLatitude:self.startAnnotation.coordinate.latitude longitude:self.startAnnotation.coordinate.longitude]; //起点

    AMapGeoPoint *endPoint = [AMapGeoPoint locationWithLatitude:self.destinationAnnotation.coordinate.latitude longitude:self.destinationAnnotation.coordinate.longitude];  //终点

    //根据已经规划的路径,起点,终点,规划类型,是否显示实时路况,生成显示方案
    self.naviRoute = [MANaviRoute naviRouteForPath:self.route.paths[self.currentRouteIndex] withNaviType:type showTraffic:NO startPoint:startPoint endPoint:endPoint];

    [self.naviRoute addToMapView:self.mapView];  //显示到地图上

    UIEdgeInsets edgePaddingRect = UIEdgeInsetsMake(RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge);

    //缩放地图使其适应polylines的展示
    [self.mapView setVisibleMapRect:[CommonUtility mapRectForOverlays:self.naviRoute.routePolylines]
                                                          edgePadding:edgePaddingRect
                                                             animated:YES];

}
//在地图上显示当前选择的路径
func presentCurrentRouteCourse() {

    if self.totalRouteNums <= 0 {
        return
    }
    self.naviRoute?.removeFromMapView() //清空地图上已有的路线

    self.infoLabel.text = "共\(UInt(self.totalRouteNums))条路线,当前显示第\(UInt(self.currentRouteIndex) + 1)条"  //提示信息

    let type = MANaviAnnotationType.riding //骑行类型

    let startPoint = AMapGeoPoint.location(withLatitude: CGFloat(self.startAnnotation.coordinate.latitude), longitude: CGFloat(self.startAnnotation.coordinate.longitude)) //起点

    let endPoint = AMapGeoPoint.location(withLatitude: CGFloat(self.destinationAnnotation.coordinate.latitude), longitude: CGFloat(self.destinationAnnotation.coordinate.longitude))  //终点

    //根据已经规划的路径,起点,终点,规划类型,是否显示实时路况,生成显示方案
    self.naviRoute = MANaviRoute(for: self.route.paths[self.currentRouteIndex], withNaviType: type, showTraffic: false, start: startPoint, end: endPoint)
    self.naviRoute?.add(to: self.mapView)

    //显示到地图上
    let edgePaddingRect = UIEdgeInsetsMake(RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge, RoutePlanningPaddingEdge)
    //缩放地图使其适应polylines的展示
    self.mapView.setVisibleMapRect(CommonUtility.mapRect(forOverlays: self.naviRoute?.routePolylines), edgePadding: edgePaddingRect, animated: true)

}

2、如何更改显示在地图上的路线的的样式(包括:出发点和目的地的图标、路线的颜色、宽度等等)。

//地图上覆盖物的渲染,可以设置路径线路的宽度,颜色等
- (MAOverlayRenderer *)mapView:(MAMapView *)mapView rendererForOverlay:(id<MAOverlay>)overlay {
    
    //虚线,如需要步行的
    if ([overlay isKindOfClass:[LineDashPolyline class]]) {
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:((LineDashPolyline *)overlay).polyline];
        polylineRenderer.lineWidth = 6;
        polylineRenderer.lineDash = YES;
        polylineRenderer.strokeColor = [UIColor redColor];
        
        return polylineRenderer;
    }
    
    //showTraffic为NO时,不需要带实时路况,路径为单一颜色
    if ([overlay isKindOfClass:[MANaviPolyline class]]) {
        MANaviPolyline *naviPolyline = (MANaviPolyline *)overlay;
        MAPolylineRenderer *polylineRenderer = [[MAPolylineRenderer alloc] initWithPolyline:naviPolyline.polyline];
        
        polylineRenderer.lineWidth = 6;
        
        if (naviPolyline.type == MANaviAnnotationTypeWalking) {
            polylineRenderer.strokeColor = self.naviRoute.walkingColor;
        } else if (naviPolyline.type == MANaviAnnotationTypeRailway) {
            polylineRenderer.strokeColor = self.naviRoute.railwayColor;
        } else {
            polylineRenderer.strokeColor = self.naviRoute.routeColor;
        }
        
        return polylineRenderer;
    }
    
    //showTraffic为YES时,需要带实时路况,路径为多颜色渐变
    if ([overlay isKindOfClass:[MAMultiPolyline class]]) {
        MAMultiColoredPolylineRenderer * polylineRenderer = [[MAMultiColoredPolylineRenderer alloc] initWithMultiPolyline:overlay];
        
        polylineRenderer.lineWidth = 6;
        polylineRenderer.strokeColors = [self.naviRoute.multiPolylineColors copy];
        
        return polylineRenderer;
    }
    
    return nil;
}

//地图上的起始点,终点,拐点的标注,可以自定义图标展示等,只要有标注点需要显示,该回调就会被调用
- (MAAnnotationView *)mapView:(MAMapView *)mapView viewForAnnotation:(id<MAAnnotation>)annotation {
    if ([annotation isKindOfClass:[MAPointAnnotation class]]) {
        
        //标注的view的初始化和复用
        static NSString *routePlanningCellIdentifier = @"RoutePlanningCellIdentifier";
        
        MAAnnotationView *poiAnnotationView = (MAAnnotationView*)[self.mapView dequeueReusableAnnotationViewWithIdentifier:routePlanningCellIdentifier];
        
        if (poiAnnotationView == nil) {
            poiAnnotationView = [[MAAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:routePlanningCellIdentifier];
        }
        
        poiAnnotationView.canShowCallout = YES;
        poiAnnotationView.image = nil;
        
        //拐点的图标标注
        if ([annotation isKindOfClass:[MANaviAnnotation class]]) {
            switch (((MANaviAnnotation*)annotation).type) {
                case MANaviAnnotationTypeRailway:
                    poiAnnotationView.image = [UIImage imageNamed:@"railway_station"];
                    break;
                    
                case MANaviAnnotationTypeBus:
                    poiAnnotationView.image = [UIImage imageNamed:@"bus"];
                    break;
                    
                case MANaviAnnotationTypeDrive:
                    poiAnnotationView.image = [UIImage imageNamed:@"car"];
                    break;
                    
                case MANaviAnnotationTypeWalking:
                    poiAnnotationView.image = [UIImage imageNamed:@"man"];
                    break;
                    
                case MANaviAnnotationTypeRiding:
                    poiAnnotationView.image = [UIImage imageNamed:@"ride"];
                    break;
                    
                default:
                    break;
            }
        }else{
            //起点,终点的图标标注
            if ([[annotation title] isEqualToString:(NSString*)RoutePlanningViewControllerStartTitle]) {
                poiAnnotationView.image = [UIImage imageNamed:@"startPoint"];  //起点
            }else if([[annotation title] isEqualToString:(NSString*)RoutePlanningViewControllerDestinationTitle]){
                poiAnnotationView.image = [UIImage imageNamed:@"endPoint"];  //终点
            }
            
        }
        
        return poiAnnotationView;
    }
    
    return nil;
}
func mapView(_ mapView: MAMapView!, rendererFor overlay: MAOverlay!) -> MAOverlayRenderer! {
    
    //虚线,如需要骑行的
    if overlay.isKind(of: LineDashPolyline.self) {
        let naviPolyline: LineDashPolyline = overlay as! LineDashPolyline
        let renderer: MAPolylineRenderer = MAPolylineRenderer(overlay: naviPolyline.polyline)
        renderer.lineWidth = 6
        renderer.strokeColor = UIColor.red
        renderer.lineDash = true
        
        return renderer
    }
    
    //showTraffic为NO时,不需要带实时路况,路径为单一颜色,比如骑行线路目前为海蓝色
    if overlay.isKind(of: MANaviPolyline.self) {
        
        let naviPolyline: MANaviPolyline = overlay as! MANaviPolyline
        let renderer: MAPolylineRenderer = MAPolylineRenderer(overlay: naviPolyline.polyline)
        renderer.lineWidth = 6
        
        if naviPolyline.type == MANaviAnnotationType.walking {
            renderer.strokeColor = naviRoute?.walkingColor
        }
        else if naviPolyline.type == MANaviAnnotationType.railway {
            renderer.strokeColor = naviRoute?.railwayColor;
        }
        else {
            renderer.strokeColor = naviRoute?.routeColor;
        }
        
        return renderer
    }
    
    //showTraffic为YES时,需要带实时路况,路径为多颜色渐变
    if overlay.isKind(of: MAMultiPolyline.self) {
        let renderer: MAMultiColoredPolylineRenderer = MAMultiColoredPolylineRenderer(multiPolyline: overlay as! MAMultiPolyline!)
        renderer.lineWidth = 6
        renderer.strokeColors = naviRoute?.multiPolylineColors
        
        return renderer
    }
    
    return nil
}

func mapView(_ mapView: MAMapView!, viewFor annotation: MAAnnotation!) -> MAAnnotationView! {
    
    if annotation.isKind(of: MAPointAnnotation.self) {
        
        //标注的view的初始化和复用
        let pointReuseIndetifier = "RoutePlanningCellIdentifier"
        var annotationView: MAAnnotationView? = mapView.dequeueReusableAnnotationView(withIdentifier: pointReuseIndetifier)
        
        if annotationView == nil {
            annotationView = MAAnnotationView(annotation: annotation, reuseIdentifier: pointReuseIndetifier)
            annotationView!.canShowCallout = true
            annotationView!.isDraggable = false
        }
        
        annotationView!.image = nil
        
        if annotation.isKind(of: MANaviAnnotation.self) {
            let naviAnno = annotation as! MANaviAnnotation
            
            switch naviAnno.type {
            case MANaviAnnotationType.railway:
                annotationView!.image = UIImage(named: "railway_station")
                break
            case MANaviAnnotationType.drive:
                annotationView!.image = UIImage(named: "car")
                break
            case MANaviAnnotationType.riding:
                annotationView!.image = UIImage(named: "ride")
                break
            case MANaviAnnotationType.walking:
                annotationView!.image = UIImage(named: "man")
                break
            case MANaviAnnotationType.bus:
                annotationView!.image = UIImage(named: "bus")
                break
            }
        }
        else {
            if annotation.title == "起点" {
                annotationView!.image = UIImage(named: "startPoint")
            }
            else if annotation.title == "终点" {
                annotationView!.image = UIImage(named: "endPoint")
            }
        }
        return annotationView!
    }
    
    return nil
}