有幾個做汽車導航的朋友問我說,他們想在地圖上制作一輛車沿着道路行駛的動畫。可是,百度地圖的道路資料并沒有公開。是以,應該怎麼辦呢?
一、
我們先來學習如何把百度地圖“弄”出來。把下面這段代碼儲存為htm格式,用浏覽器打開,就能看到百度地圖了。
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<title>點沿直線運動</title>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=1.2&services=true"></script>
</head>
<body>
<div style="width:520px;height:340px;border:1px solid gray" id="container"></div>
</body>
</html>
<script type="text/javascript">
var map = new BMap.Map("container"); //建立地圖容器
map.centerAndZoom(new BMap.Point(116.404, 39.915), 15); //設定中心點和地圖級别
</script>
二、
再分析一下汽車導航制作者的這個需求:
1、車輛——用自定義圖檔的marker實作
var carMk = new BMap.Marker(pts[0],{icon:myIcon});
var myIcon = new BMap.Icon("Mario.png", new BMap.Size(32, 70), { //小車圖檔
//offset: new BMap.Size(0, -5), //相當于CSS精靈
imageOffset: new BMap.Size(0, 0) //圖檔的偏移量。為了是圖檔底部中心對準坐标點。
});
2、擷取道路資料——雖然百度地圖API并未公開道路層資料,但我們可以巧妙的“拿到”。具體請往下看。
三、
如何利用百度地圖API拿到道路層的資料呢?
答案很簡單:駕車導航。
首先讨論一下,為什麼要用駕車導航,而不用步行和公交導航?
1、步行導航:步行導航顯然能“穿越”公園、甚至小區,得到的肯定不是道路層的資料;
2、公交導航:公交導航雖然都是道路層的資料,但很局限,因為隻有有公共汽車的地方,才有公交方案。并且,公交方法是包含了地鐵線路的。
3、駕車導航:擁有所有道路層的資料,并且沒有地鐵、小區裡、花園内這樣的無效資料。
駕車導航示例:
var myP1 = new BMap.Point(116.380967,39.913285); //起點
var myP2 = new BMap.Point(116.424374,39.914668); //終點
var driving2 = new BMap.DrivingRoute(map, {renderOptions:{map: map, autoViewport: true}}); //駕車執行個體
driving2.search(myP1, myP2); //顯示一條公交線路
四、
那麼,如何獲得道路層的資料呢?
我們可以想象一下,駕車導航的路線,在API中是屬于折線。
折線是由無數的點構成的。
也就是說,隻要找到這些點,我們就能擷取道路層的資料了。
我們發現,Route裡有個接口getPath,可以獲得路線的地理坐标點數組。并且,以point數組的形式傳回。
利用建立好的駕車執行個體DrivingRoute,先search,得到一個駕車方案;
駕車方案中,選擇第一條Route;
最後獲得該Route的全部點。
注意,由于ajax的異步加載機制,我們需要利用搜尋後的回調函數setSearchCompleteCallback,來進行道路資料的獲得。
driving.setSearchCompleteCallback(function(){
var pts = driving.getResults().getPlan(0).getRoute(0).getPath(); //通過駕車執行個體,獲得一系列點的數組
var paths = pts.length; //獲得有幾個點
}
五、
道路資料擷取完畢。接下來是汽車圖檔的展示。可以通過改變marker的坐标點來實作,改變marker坐标的接口setPosition。
我們假設每100毫秒改變一次,利用延時函數setTimeout。
同樣,由于ajax異步加載原因,需要異步給i指派。
i=0;
function resetMkPoint(i){
carMk.setPosition(pts[i]);
if(i < paths){
setTimeout(function(){
i++;
resetMkPoint(i);
},100);
resetMkPoint(1);
console.log(i);
},100)
六、

點選左側的“開始”按鈕,動畫開始播放。
點選下側的“擷取代碼”按鈕,可得到全部源代碼。
七、
最後,放出全部源代碼:
<input type="button" value="開始" onclick="run();" />
var map = new BMap.Map("container");
map.centerAndZoom(new BMap.Point(116.404, 39.915), 15);
function run(){
var driving = new BMap.DrivingRoute(map); //駕車執行個體
driving.search(myP1, myP2);
map.addOverlay(carMk);
resetMkPoint(5);