本文將向大家介紹如何使用百度地圖API提供的駕車(chē)導(dǎo)航服務(wù)進(jìn)行開(kāi)發(fā)。
一個(gè)簡(jiǎn)單的示例
駕車(chē)導(dǎo)航服務(wù)根據(jù)傳入的起點(diǎn)和終點(diǎn)信息給出從起點(diǎn)到終點(diǎn)的駕車(chē)路線,我們先從一個(gè)最簡(jiǎn)單的示例看起:
var map = new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
var driving = new BMap.DrivingRoute(map, {
renderOptions: {
map: map
}
});
driving.search('圓明園', '西單');
上面代碼很簡(jiǎn)單,先初始化地圖(地圖容器的html代碼省略),接著實(shí)例化一個(gè)DrivingRoute類(lèi),并配置好參數(shù)(參數(shù)具體含義后續(xù)再說(shuō))。最后調(diào)用該實(shí)例的search方法進(jìn)行駕車(chē)方案查詢(xún)。我們會(huì)在瀏覽器看到如下效果:
DrivingRoute的構(gòu)造函數(shù)的第一個(gè)參數(shù)制定檢索的范圍,這里我們傳遞的是map實(shí)例,也就是說(shuō)駕車(chē)導(dǎo)航的位置會(huì)根據(jù)當(dāng)前地圖中心點(diǎn)所在的城市進(jìn)行檢索。當(dāng)然你也可以傳遞一個(gè)城市名稱(chēng)的字符串:
var driving = new BMap.DrivingRoute("北京", {
renderOptions: {
map: map
}
});
DrivingRoute的構(gòu)造函數(shù)第二個(gè)參數(shù)是可選的配置,類(lèi)型為DrivingRouteOptions。這里我們只使用了renderOptions屬性,這個(gè)屬性值的類(lèi)型為DrivingRenderOptions類(lèi),它是用來(lái)控制檢索結(jié)果的呈現(xiàn)的,比如是否將結(jié)果線路呈現(xiàn)在地圖上,是否將詳細(xì)方案描述呈現(xiàn)在頁(yè)面的某個(gè)位置等等。這里我們使用了map屬性,即讓檢索結(jié)果自動(dòng)展現(xiàn)在地圖上,這樣我們就會(huì)看到地圖上有起點(diǎn)、終點(diǎn)以及它們之間的線路了。
其他發(fā)起檢索的方式
除了使用字符串方式發(fā)起駕車(chē)檢索以外,還可以使用坐標(biāo)發(fā)起:
driving.search(new BMap.Point(116.404, 39.915), new BMap.Point(116.389, 39.811));
使用坐標(biāo)發(fā)起檢索時(shí),起點(diǎn)和終點(diǎn)沒(méi)有具體的描述,僅僅用“起點(diǎn)”和“終點(diǎn)”進(jìn)行描述。
通過(guò)文檔看,search還支持LocalResultPoi類(lèi)型,該類(lèi)型沒(méi)有構(gòu)造函數(shù),但是可以通過(guò)字面量形式表示。我們可以自己構(gòu)造這個(gè)類(lèi)型的實(shí)例并發(fā)起駕車(chē)檢索:
driving.search({title: '我的家', point: new BMap.Point(116.410, 39.915)}, {title: '你的家', point: new BMap.Point(116.400, 39.910)});
這樣,API就會(huì)用開(kāi)發(fā)者自定義的名稱(chēng)進(jìn)行顯示。當(dāng)然通過(guò)LocalSearch獲取的結(jié)果類(lèi)型也是LocalResultPoi,也可以直接將結(jié)果對(duì)象傳遞到search方法中。
呈現(xiàn)設(shè)置
除了設(shè)置展現(xiàn)的地圖以外,呈現(xiàn)設(shè)置中還有很多其他功能,最常用的就是將詳細(xì)方案描述顯示在頁(yè)面上:
!DOCTYPE html
html
head
meta charset="utf-8"/
title 駕車(chē)導(dǎo)航 /title
script src="api.map.baidu/api?v=1.2" /script
/head
body
div id="container" /div
div id="panel" /div
script
var map =new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
var driving =new BMap.DrivingRoute(map, {
renderOptions: {
map: map,
panel: 'panel'
}
});
driving.search('圓明園', '西單');
/script
/body
/html
這里我們?cè)黾右粋€(gè)div,id為panel,接著在renderOptions中增加panel屬性,把div的id傳遞進(jìn)去。我們會(huì)看到如下效果:
API會(huì)將詳細(xì)的駕車(chē)方案描述填充到id為panel的div容器中。此時(shí)點(diǎn)擊panel中的具體方案會(huì)在圖區(qū)產(chǎn)生交互效果。
另外,呈現(xiàn)設(shè)置的enableDragging如果設(shè)置為true的畫(huà),則用戶(hù)可以在地圖上拖拽起點(diǎn)、終點(diǎn)改變駕車(chē)方案,也可以任意拖拽修改途徑點(diǎn):
var driving = new BMap.DrivingRoute(map, {
renderOptions: {
map: map,
panel: 'panel',
enableDragging: true
}
});
highlightMode屬性可以控制點(diǎn)擊panel中的方案描述時(shí)展示點(diǎn)位置還是展示一段路線,它支持如下兩個(gè)值:
BMAP_HIGHLIGHT_STEP:展現(xiàn)關(guān)鍵點(diǎn) BMAP_HIGHLIGHT_ROUTE:展現(xiàn)路段默認(rèn)為展現(xiàn)關(guān)鍵點(diǎn),如下圖:
點(diǎn)擊描述的第三項(xiàng),顯示一個(gè)關(guān)鍵點(diǎn)信息(根據(jù)描述,這個(gè)點(diǎn)就是在中關(guān)村一橋左轉(zhuǎn)的位置點(diǎn)),也可以顯示路線:
這時(shí),再選中第三步的時(shí)候,地圖展現(xiàn)的是一段線路(即“沿中關(guān)村北大街行駛1.6公里”這段路)。
駕車(chē)策略配置
在DrivingRouteOptions還有一個(gè)控制策略的屬性drivingPolicy,它的屬性值可以為以下幾種:
BMAP_DRIVING_POLICY_LEAST_TIME:最少時(shí)間,默認(rèn) BMAP_DRIVING_POLICY_LEAST_DISTANCE:最短距離 BMAP_DRIVING_POLICY_AVOID_HIGHWAYS:避開(kāi)高速通過(guò)配置策略可獲得不同的駕車(chē)方案。
回調(diào)函數(shù)
在DrivingRouteOptions里面還有很多回調(diào)函數(shù)屬性,比如:onSearchComplete、onMarkersSet、onInfoHtmlSet、onPolylinesSet和onResultsHtmlSet。在DrivingRoute類(lèi)上也有對(duì)應(yīng)的設(shè)置回調(diào)的方法:setSearchCompleteCallback、setMarkersSetCallback等等。實(shí)際上不論通過(guò)配置參數(shù)傳遞還是通過(guò)接口設(shè)置回調(diào),其作用都是一樣的。這些回調(diào)到底有什么用處呢?
通過(guò)回調(diào)函數(shù),開(kāi)發(fā)者可獲得更多的數(shù)據(jù)資源,可以利用這些數(shù)據(jù)資源更好、更靈活的進(jìn)行二次開(kāi)發(fā)。下面這個(gè)示例就是利用onSearchComplete獲取數(shù)據(jù)自行添加覆蓋物和描述信息:
!DOCTYPE html
html
head
meta charset="utf-8"/
title 駕車(chē)導(dǎo)航 /title
script src="api.map.baidu/api?v=1.2" /script
/head
body
div id="container" /div
div id="panel" /div
script
var map =new BMap.Map('container');
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11);
var driving =new BMap.DrivingRoute(map, {
onSearchComplete: function(results){
if (driving.getStatus() == BMAP_STATUS_SUCCESS) {
// 地圖覆蓋物
addOverlays(results);
// 方案描述
addText(results);
}
}
});
driving.search('圓明園', '西單');
// 添加覆蓋物并設(shè)置視野
function addOverlays(results) {
// 自行添加起點(diǎn)和終點(diǎn)
var start = results.getStart();
var end = results.getEnd();
addStart(start.point, start.title);
addEnd(end.point, end.title);
var viewPoints = [start.point, end.point];
// 獲取方案
var plan = results.getPlan(0);
// 獲取方案中包含的路線
for (var i =0; i plan.getNumRoutes(); i ++) {
addRoute(plan.getRoute(i).getPath());
viewPoints.concat(plan.getRoute(i).getPath());
}
// 設(shè)置地圖視野
map.setViewport(viewPoints, {
margins: [40, 10, 10, 10]
});
}
// 添加方案描述
function addText(results) {
var plan = results.getPlan(0);
// 獲取方案中包含的路線
var htmls = [];
for (var i =0; i plan.getNumRoutes(); i ++) {
var route = plan.getRoute(i);
for (var j =0; j route.getNumSteps(); j ++) {
var curStep = route.getStep(j);
htmls.push((j +1) +'. '+ curStep.getDescription() +' br / ');
}
}
var panel = document.getElementById('panel');
panel.innerHTML = htmls.join('');
panel.style.lineHeight ='1.4em';
panel.style.fontSize ='12px';
}
// 添加起點(diǎn)覆蓋物
function addStart(point, title){
map.addOverlay(new BMap.Marker(point, {
title: title,
icon: new BMap.Icon('blue.png', new BMap.Size(38, 41), {
anchor: new BMap.Size(4, 36)
})}));
}
// 添加終點(diǎn)覆蓋物
function addEnd(point, title){
map.addOverlay(new BMap.Marker(point, {
title: title,
icon: new BMap.Icon('red.png', new BMap.Size(38, 41), {
anchor: new BMap.Size(4, 36)
})}));
}
// 添加路線
function addRoute(path){
map.addOverlay(new BMap.Polyline(path, {
strokeColor: '#333',
enableClicking: false
}));
}
/script
/body
/html
在上面的代碼中,我們初始化DrivingRoute實(shí)例時(shí)沒(méi)有設(shè)置renderOptions,也就是說(shuō)駕車(chē)導(dǎo)航的結(jié)果不會(huì)自動(dòng)添加到地圖上,描述信息也不會(huì)展現(xiàn)在頁(yè)面中,我們通過(guò)onSearchComplete獲取數(shù)據(jù)自行添加。onSearchComplete回調(diào)函數(shù)的參數(shù)為一個(gè)DrivingRouteResult對(duì)象,通過(guò)它可以獲取數(shù)據(jù)信息。在回調(diào)函數(shù)中我們首先判斷一下檢索是否成功,如果成功則添加覆蓋物和描述信息。在添加覆蓋物完成后,我們調(diào)用了Map的setViewport方法來(lái)設(shè)置視野,以便讓結(jié)果完整展示在地圖當(dāng)中。在獲取方案的時(shí)候我們調(diào)用getPlan方法并給定索引0,這表示獲取第一條駕車(chē)方案(實(shí)際上目前僅有一條駕車(chē)方案,但是以后可能會(huì)同時(shí)給出多條方案)。每個(gè)方案通過(guò)RoutePlan描述,方案中會(huì)包含若干Route對(duì)象,它表示兩點(diǎn)間的線路(在只有一個(gè)目的地的情況下,Route對(duì)象數(shù)量總為1),Route對(duì)象又包含若干Step,通過(guò)getStep方法可獲得,Step對(duì)象描述了每一個(gè)關(guān)鍵點(diǎn)的信息。
以上代碼在瀏覽器中的效果如下:
通過(guò)接口,你還可以進(jìn)一步豐富這個(gè)功能,比如增加一些點(diǎn)擊交互。
需要注意的問(wèn)題
搜索沒(méi)有結(jié)果
如果檢索關(guān)鍵字過(guò)于模糊,比如從“麥當(dāng)勞”到“肯德基”,這樣API不知道從哪個(gè)麥當(dāng)勞到哪個(gè)肯德基,所以此時(shí)將無(wú)法獲取導(dǎo)航線路。為了讓導(dǎo)航返回更準(zhǔn)確的結(jié)果,建議使用Point類(lèi)型或LocalSearchPoi類(lèi)型發(fā)起檢索。
發(fā)起新檢索后地圖沒(méi)有清除上一次結(jié)果
在一般情況下,你只需要一個(gè)DrivingRoute實(shí)例做檢索,同一個(gè)實(shí)例在檢索的時(shí)候會(huì)自動(dòng)清除上一次檢索的結(jié)果(包括地圖覆蓋物和描述)。但是如果每次檢索都new一個(gè)新的DrivingRoute實(shí)例,那么每個(gè)實(shí)例的檢索結(jié)果都會(huì)出現(xiàn)在地圖上,無(wú)法自動(dòng)清除。