百度地圖API詳解之駕車導航
本文將向大家介紹如何使用百度地圖API提供的駕車導航服務進行開發。
一個簡單的示例
駕車導航服務根據傳入的起點和終點資訊給出從起點到終點的駕車路線,我們先從一個最簡單的示例看起:
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('圓明園', '西單');
上面程式碼很簡單,先初始化地圖(地圖容器的html程式碼省略),接著例項化一個DrivingRoute類,並配置好引數(引數具體含義後續再說)。最後呼叫該例項的search方法進行駕車方案查詢。我們會在瀏覽器看到如下效果:
DrivingRoute的建構函式的第一個引數制定檢索的範圍,這裡我們傳遞的是map例項,也就是說駕車導航的位置會根據當前地圖中心點所在的城市進行檢索。當然你也可以傳遞一個城市名稱的字串:
var driving = new BMap.DrivingRoute("北京", { renderOptions: { map: map } });
DrivingRoute的建構函式第二個引數是可選的配置,型別為DrivingRouteOptions。這裡我們只使用了renderOptions屬性,這個屬性值的型別為DrivingRenderOptions類,它是用來控制檢索結果的呈現的,比如是否將結果線路呈現在地圖上,是否將詳細方案描述呈現在頁面的某個位置等等。這裡我們使用了map屬性,即讓檢索結果自動展現在地圖上,這樣我們就會看到地圖上有起點、終點以及它們之間的線路了。
其他發起檢索的方式
除了使用字串方式發起駕車檢索以外,還可以使用座標發起:
driving.search(new BMap.Point(116.404, 39.915), newBMap.Point(116.389, 39.811));
使用座標發起檢索時,起點和終點沒有具體的描述,僅僅用“起點”和“終點”進行描述。
通過文件看,search還支援LocalResultPoi型別,該型別沒有建構函式,但是可以通過字面量形式表示。我們可以自己構造這個型別的例項併發起駕車檢索:
driving.search({title: '我的家', point: new BMap.Point(116.410, 39.915)}, {title: '你的家', point: new BMap.Point(116.400, 39.910)});
這樣,API就會用開發者自定義的名稱進行顯示。當然通過LocalSearch獲取的結果型別也是LocalResultPoi,也可以直接將結果物件傳遞到search方法中。
呈現設定
除了設定展現的地圖以外,呈現設定中還有很多其他功能,最常用的就是將詳細方案描述顯示在頁面上:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>駕車導航</title> <script src="http://api.map.baidu.com/api?v=1.2"></script> </head> <body> <div id="container" style="width:400px;height:248px"></div> <div id="panel" style="position:absolute;left:420px;top:10px"></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>
這裡我們增加一個div,id為panel,接著在renderOptions中增加panel屬性,把div的id傳遞進去。我們會看到如下效果:
API會將詳細的駕車方案描述填充到id為panel的div容器中。此時點選panel中的具體方案會在圖區產生互動效果。
另外,呈現設定的enableDragging如果設定為true的畫,則使用者可以在地圖上拖拽起點、終點改變駕車方案,也可以任意拖拽修改途徑點:
var driving = new BMap.DrivingRoute(map, { renderOptions: { map: map, panel: 'panel', enableDragging: true } });
highlightMode屬性可以控制點選panel中的方案描述時展示點位置還是展示一段路線,它支援如下兩個值:
- BMAP_HIGHLIGHT_STEP:展現關鍵點
- BMAP_HIGHLIGHT_ROUTE:展現路段
預設為展現關鍵點,如下圖:
點選描述的第三項,顯示一個關鍵點資訊(根據描述,這個點就是在中關村一橋左轉的位置點),也可以顯示路線:
這時,再選中第三步的時候,地圖展現的是一段線路(即“沿中關村北大街行駛1.6公里”這段路)。
駕車策略配置
在DrivingRouteOptions還有一個控制策略的屬性drivingPolicy,它的屬性值可以為以下幾種:
- BMAP_DRIVING_POLICY_LEAST_TIME:最少時間,預設
- BMAP_DRIVING_POLICY_LEAST_DISTANCE:最短距離
- BMAP_DRIVING_POLICY_AVOID_HIGHWAYS:避開高速
通過配置策略可獲得不同的駕車方案。
回撥函式
在DrivingRouteOptions裡面還有很多回調函式屬性,比如:onSearchComplete、onMarkersSet、onInfoHtmlSet、onPolylinesSet和onResultsHtmlSet。在DrivingRoute類上也有對應的設定回撥的方法:setSearchCompleteCallback、setMarkersSetCallback等等。實際上不論通過配置引數傳遞還是通過介面設定回撥,其作用都是一樣的。這些回撥到底有什麼用處呢?
通過回撥函式,開發者可獲得更多的資料資源,可以利用這些資料資源更好、更靈活的進行二次開發。下面這個示例就是利用onSearchComplete獲取資料自行新增覆蓋物和描述資訊:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"/> <title>駕車導航</title> <script src="http://api.map.baidu.com/api?v=1.2"></script> </head> <body> <div id="container" style="width:400px;height:248px"></div> <div id="panel" style="position:absolute;left:420px;top:10px"></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('圓明園', '西單'); // 新增覆蓋物並設定視野function addOverlays(results) { // 自行新增起點和終點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()); } // 設定地圖視野 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'; } // 新增起點覆蓋物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) })})); } // 新增終點覆蓋物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例項時沒有設定renderOptions,也就是說駕車導航的結果不會自動新增到地圖上,描述資訊也不會展現在頁面中,我們通過onSearchComplete獲取資料自行新增。onSearchComplete回撥函式的引數為一個DrivingRouteResult物件,通過它可以獲取資料資訊。在回撥函式中我們首先判斷一下檢索是否成功,如果成功則新增覆蓋物和描述資訊。在新增覆蓋物完成後,我們呼叫了Map的setViewport方法來設定視野,以便讓結果完整展示在地圖當中。在獲取方案的時候我們呼叫getPlan方法並給定索引0,這表示獲取第一條駕車方案(實際上目前僅有一條駕車方案,但是以後可能會同時給出多條方案)。每個方案通過RoutePlan描述,方案中會包含若干Route物件,它表示兩點間的線路(在只有一個目的地的情況下,Route物件數量總為1),Route物件又包含若干Step,通過getStep方法可獲得,Step物件描述了每一個關鍵點的資訊。
以上程式碼在瀏覽器中的效果如下:
通過介面,你還可以進一步豐富這個功能,比如增加一些點選互動。
需要注意的問題
搜尋沒有結果
如果檢索關鍵字過於模糊,比如從“麥當勞”到“肯德基”,這樣API不知道從哪個麥當勞到哪個肯德基,所以此時將無法獲取導航線路。為了讓導航返回更準確的結果,建議使用Point型別或LocalSearchPoi型別發起檢索。
發起新檢索後地圖沒有清除上一次結果
在一般情況下,你只需要一個DrivingRoute例項做檢索,同一個例項在檢索的時候會自動清除上一次檢索的結果(包括地圖覆蓋物和描述)。但是如果每次檢索都new一個新的DrivingRoute例項,那麼每個例項的檢索結果都會出現在地圖上,無法自動清除。