百度地图API详解之公交路线规划

什么是公交路线规划

公交导航功能是告诉使用者从A到B的公交出行方案,而不是某条具体的公交线路信息,这一点需要广大开发者注意。

公交导航功能通过类TransitRoute来实现,这里需要说说为啥不是BusRoute,而是TransitRoute。百度提供的是公共交通导航,公共交通不仅仅涉及bus,可能还会有地铁、渡轮甚至以后的飞机火车,所以这里使用的是public transit中的transit进行描述。

一个简单的例子

我们还是从一个简单的例子开始:

1
2
3
4
5
6
7
var transit = new BMap.TransitRoute( '北京' , {
     renderOptions: {
         map: map,
         panel: 'panel'
     }
});
transit.search( '西单' , '颐和园' );

       代码通过renderOptions设置渲染的地图实例和侧栏面板容器的id,其中map是已经实例化好的地图,panel为已经准备好的div元素的id。我们会看到如下结果:

2011110614423814

地图上显示了一个方案,在面板中列出了所有方案的描述,点击不同的方案地图会予以展示。

除了使用字符串类型以外,还可以提供坐标进行查询,这样可以得到更精确的结果。比如从“麦当劳”到“肯德基”这样的路线查询就不会得到结果,因为API不知道是从哪个麦当劳到哪个肯德基。下面的示例使用了坐标进行搜索。

1
2
transit.search( new BMap.Point(116.315157,39.987946),
                new BMap.Point(116.371499,39.880394));

下面是使用坐标作为参数进行查询得到的结果:

2011110614434713

注意,由于提供的是坐标,所以起点和终点没有具体的地点描述。

和驾车导航类似,起点和终点也可以是LocalResultPoi类型,我们还是用上面的坐标进行查询,不过是封装在一个LocalResultPoi类型当中的:

1
2
transit.search({title: '我这里' , point: new BMap.Point(116.315157,39.987946)},
                {title: '你这里' , point: new BMap.Point(116.371499,39.880394)});

这样API在展示结果时就可以显示起点和终点的描述了。

 

自定义覆盖物展示

如果你不满意API提供的默认线路的颜色和标注的样式,你也可以选择通过通过数据接口自行创建。注意,自己创建覆盖物时,点击列表中的方案将不会更新地图区域,因为此时地图区域的元素都是由开发者自行创建的。在使用数据接口之前,先通过一个结构图来了解一个完整的公交方案的各个组成部分,以方便理解:

2011102120443114

一个不需要换乘的公交方案是由:起点、起点到上车站的步行线路、上车站到下车站的公交线路以及下车站到终点的步行线路构成。当然有可能起点和上车站是重合的,或者终点和下车站是重合的,此时步行线路长度就为0(起点或终点本身就为公交站的时候)。如果有换乘,那么每次换乘中的下车站到上车站也有步行线路(如上图的第二个方案所示)。

所以不论公交方案具体是什么样,在数据上的表示都是一致的:

  • 直达方案:2条步行线路 + 1条公交线路
  • 换乘一次方案:3条步行线路 + 2条公交线路
  • 换乘两次方案:4条步行线路 + 3条公交线路

以此类推。

API中通过TransitRouteResult来描述公交导航结果,通过TransitRoutePlan来描述一条公交方案。那么怎么获取公交导航结果和具体的方案的信息呢?请看下面的示例:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
var transit = new BMap.TransitRoute( '北京' , {
     onSearchComplete: function (result) {
         if (transit.getStatus() == BMAP_STATUS_SUCCESS) {
             // 从结果对象中获取起点和终点信息
             var start = result.getStart();
             var end = result.getEnd();
             addStart(start.point, start.title);
             addEnd(end.point, end.title);
             // 直接获取第一个方案
             var plan = result.getPlan(0);
             // 遍历所有步行线路
             for ( var i = 0; i < plan.getNumRoutes(); i++) {
                 if (plan.getRoute(i).getDistance( false ) > 0) {
                     // 判断只有大于0的步行线路才会绘制
                     addWalkRoute(plan.getRoute(i).getPath());
                 }
             }
             // 遍历所有公交线路
             var allLinePath = [];
             for (i = 0; i < plan.getNumLines(); i++) {
                 allLinePath = allLinePath.concat(plan.getLine(i).getPath());
                 addLine(plan.getLine(i).getPath());
             }
             // 最后根据公交线路的点设置地图视野
             map.setViewport(allLinePath);
         }
     }
});
 
transit.search( '北京大学' , '北京交通大学' );
 
// 添加起点覆盖物
function addStart(point, title){
     map.addOverlay( new BMap.Marker(point, {
         title: title,
         icon: new BMap.Icon( 'http://images.cnblogs.com/cnblogs_com/jz1108/329471/o_blue.png' ,
                             new BMap.Size(38, 41), {
                                 anchor: new BMap.Size(4, 36)
                             }
         )}));
}
 
// 添加终点覆盖物
function addEnd(point, title){
     map.addOverlay( new BMap.Marker(point, {
         title: title,
         icon: new BMap.Icon( 'http://images.cnblogs.com/cnblogs_com/jz1108/329471/o_red.png' , new BMap.Size(38, 41), {
             anchor: new BMap.Size(4, 36)
         })}));
}
 
// 添加路线
function addWalkRoute(path){
     map.addOverlay( new BMap.Polyline(path, {
         strokeColor: 'black' ,
         strokeOpacity: 0.7,
         strokeWeight: 4,
         strokeStyle: 'dashed' ,
         enableClicking: false
     }));
}
 
function addLine(path){
     map.addOverlay( new BMap.Polyline(path, {
         strokeColor: 'blue' ,
         strokeOpacity: 0.6,
         strokeWeight: 5,
         enableClicking: false
     }));
}

在上面的代码中,通过TransitRouteOptions的onSearchComplete属性设置了回调函数,一旦检索完成这个回调函数就会被调用。在回调函数开始我们先判断检索是否成功,如果成功表示至少有一条公交方案返回,这里我们先通过结果对象获取起点和终点,接着直接获取第一条方案,遍历方案中所有步行线路和公交线路并绘制在地图上,最后我们根据公交线路的点来设置一个合适的地图视野。

你会在浏览器中得到如下效果:

2011110614303796

在获取结果对象时,除了通过回调函数参数获取以外,还可以通过TransitRoute的getResults方法获得,需要注意的是,由于搜索过程是异步的,以下代码的写法将不会得到结果:

1
2
transit.search( '西单' , '颐和园' );
var res = transit.getResults();  // undefined

因为search方法调用结束后搜索结果并没有立即返回。开发者可以在回调函数中调用此方法立即获得结果,也可以等回调函数执行完若干时间后再想获取结果数据时调用。

自定义方案描述

通过TransitRoutePlan的getDescription可以获得完整的方案描述,但是如果开发者想自行定义描述的形式则可通过数据接口进行。例如:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
var transit = new BMap.TransitRoute( '北京' , {
     onSearchComplete: function (result) {
         if (transit.getStatus() == BMAP_STATUS_SUCCESS) {
             // 从结果对象中获取起点和终点信息
             var start = result.getStart().title;
             var end = result.getEnd().title;
             
             // 直接获取第一个方案
             var plan = result.getPlan(0);
             // 获取步行线路与公交线路个数总和,用于遍历
             var total = plan.getNumRoutes() + plan.getNumLines();
             
             var description = [ '从' + start];
             var addEndTitle = true ;
             for ( var i = 0; i < total; i++) {
                 if (i % 2 == 0) {
                     // i为偶数
                     // 处理第一个步行描述逻辑
                     if (i / 2 == 0) {
                         if (plan.getRoute(i / 2).getDistance( false ) == 0) {
                             description = [ '从' ];
                         }
                     }
                     // 处理最后一个步行描述逻辑
                     if (i / 2 == plan.getNumRoutes() - 1) {
                         if (plan.getRoute(i / 2).getDistance( false ) == 0) {
                             addEndTitle = false ;
                         }
                     }
                     if (plan.getRoute(i / 2).getDistance( false ) > 0) {
                         description.push( '步行约' + plan.getRoute(i / 2).getDistance( true ) + '至' );
                     }
                 } else {
                     // i为奇数
                     var line = plan.getLine((i - 1) / 2);
                     if (i == 0) {
                         description.push(line.getGetOnStop().title + ', ' );
                     }
                     if (i > 0) {
                         if (plan.getRoute((i - 1) / 2).getDistance( false ) > 0) {
                             description.push(line.getGetOnStop().title + ', ' );
                         }
                     }
                     description.push( '乘坐' + line.title + ', ' );
                     description.push( '经过' + line.getNumViaStops() + '站' );
                     description.push( '在' + line.getGetOffStop().title + '站下车,' );
                 }
             }
             if (addEndTitle) {
                 description.push(end + '。' );
             }
             // 替换可能出现的末尾位置的逗号
             var descriptionStr = description.join( '' ).replace(/uff0c$/, '。' );
         }
     }
});
 
transit.search( '北京大学' , '北京交通大学' );

变量descriptionStr的内容为:“从北京大学步行约60米至北京大学西门, 乘坐运通106(中央党校北门-田村北路), 经过6站在中国农业科学院站下车,乘坐26(二里庄-西便门), 经过4站在北京交通大学站下车。”。

回调函数详解

前面的几个例子我们使用了onSearchComplete回调函数,在API中还提供了如下几个回调函数,它们的含义和触发时机如下:

  • onMarkersSet:如果设置了渲染的地图,则API自动添加标注后会触发此函数。
  • onPolylinesSet:如果设置了渲染的地图,则API自动添加线路覆盖物后会触发此函数。
  • onInfoHtmlSet:如果设置了渲染地图,当用户点击标注弹出信息窗口时会触发此函数。
  • onResultsHtmlSet:如果设置了渲染侧栏,则API填充完HTML后会触发此函数。



Sup_Heaven的专栏

Sup_Heaven的专栏

Sup_Heaven

Sup_Heaven

Sup_Heaven

Sup_Heaven

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值