1.使用百度地圖API制作軌跡播放;
可應用於車輛跟蹤、行駛線路回放、跑步行程的記錄等地圖應用場景,
1.1繪制靜態軌跡圖
獲取多個軌跡點point(必須包含經度、緯度)
使用polyline對象依次連接相鄰的2個點(注意polyline的個數比point的少1)
1.2繪制動態軌跡圖(固定間隔時間)
每隔500毫秒讀取一個軌跡點,實現a,b兩個功能
a增加一條polyline
b將marker從先前的point移到當前點
主方法使用setTimeout方法迭代來實現動態循環
Polyline在每條迭代循環體中添加即可,marker的移動則可以通過2中方法來實現:
一、使用removeOverlay除去原marker並在當前point處添加新marker
這是當時做項目時想到的方法,由於先前繪制polyline時使用addOverlay的思維慣性,在繪制marker時也就繼續使用了addOverlay做循環迭代。
window.run = function (){
var pts ={?????}//你獲取到的一系列點的數組(通過gps或其他接口)
var paths = pts.length; //獲得有幾個點
var carMk = new BMap.Marker(pts[0],{icon:myIcon});
map.addOverlay(carMk);
i=0;
function removeMkPoint(i){
if(i < paths){//
setTimeout(function(){
i++;
map.removeOverlay(carMk);//清除前一個marker
removeMkPoint(i);
},100);
}
}
setTimeout(function(){
resetMkPoint(5);
},100)
});
}
setTimeout(function(){
run();
},1500);
二、使用marker的setPosition方法重新設置marker的位置
在項目完成后,我又讀了一篇百度api的文檔,發現官方demo中使用setPosition方法能很好地實現marker的移動功能
window.run = function (){
var pts ={?????}//你獲取到的一系列點的數組(通過gps或其他接口)
var paths = pts.length; //獲得有幾個點
var carMk = new BMap.Marker(pts[0],{icon:myIcon});
map.addOverlay(carMk);
i=0;
function resetMkPoint(i){
carMk.setPosition(pts[i]);//重新設置marker的position
if(i < paths){
setTimeout(function(){
i++;
resetMkPoint(i);
},100);
}
}
setTimeout(function(){
resetMkPoint(5);
},100)
});
}
setTimeout(function(){
run();
},1500);
注意:marker的opts屬性能自定義marker的icon(汽車、人等圖標)、旋轉方向、大小、偏移等等屬性,另外setAnimation方法還能設置動畫效果。
1.3繪制polyline
軌跡線路是由一個一個polyline首尾相連組合起來的,因此,只需要在每次添加marker時添加一個polyline即可,並且在下一輪迭代循環中不需要清除,每條polyline的首尾2個端點就是當前點和上一個時間段的點
var pts0,前一個點 var pts1當前點
var carPl=new BMap.Polyline([pts0,pts1],{strokeColor:'blue',strokeWeight:4,strokeOpacity:0.8});
map.addOverlay(carPl);
pts0=pts1;//每次添加polyline后當前點變為前一個點
1.4添加播放按鈕控件控制軌跡播放
添加自定義的播放控件,這里需要使用prototype屬性來返回對象類型原型的引用, 這里給出prototype的理解
例如:A.prototype = new B();
理解prototype不應把它和繼承混淆。A的prototype為B的一個實例,可以理解A將B中的方法和屬性全部克隆了一遍。這里強調的是克隆而不是繼承,其區別在於:A的prototype是B的實例,同時B的prototype也可能是A的實例。
A能使用B的方法和屬性,當A、B中都有方法名為f的方法時,A的實例instance調用這個f方法(instance.f)會是A自生的f方法而不是B的f方法,如果A的實例instance想調用B的f方法,需要使用call方法來實現:先new一個B的實例var Binstance=new B(); Binstance.f.call(instance);
function PlayControl(){
// 默認停靠位置和偏移量
this.defaultAnchor = BMAP_ANCHOR_BOTTOM_RIGHT;
this.defaultOffset = new BMap.Size(10, 40);
}
// 通過JavaScript的prototype屬性繼承於BMap.Control
PlayControl.prototype = new BMap.Control();
// 自定義控件必須實現自己的initialize方法,並且將控件的DOM元素返回
// 在本方法中創建個input元素作為控件的容器,並將其添加到地圖容器中
PlayControl.prototype.initialize = function(map){
// 創建一個DOM元素
var input = document.createElement("input");
input.id="playCtrl";
input.type="image";
input.src="image/play.png";
input.onclick=startPlay();//startPlay為上一步開始執行setTimeout迭代
};
// 添加DOM元素到地圖中
map.getContainer().appendChild(input);
// 將DOM元素返回
return input;
};
// 創建控件
var myPlayCtrl = new PlayControl();
// 添加到地圖當中
map.addControl(myPlayCtrl);
1.5將播放按鈕設計為可以單擊切換播放和停止的按鈕
定義一個變量var i=0,在onclick事件觸發時,將i在0和1之間不停切換,根據i的值來判斷執行開始播放方法和停止方法。
停止播放方法可以通過clearTimeout(timer)來實現(前提是在前面的開始播放方法中將setTimeout語句作為字符串賦值為timer),並使用removeOverlay來清除播放過程中出現的痕跡。
input.onclick=function(){
if(i==0){
startPlay();//播放開始
input.src="image/pause.png";
i=1;
}else{
pausePlay();//播放停止
input.src="image/play.png";
i=0;
}
};
1.6添加播放速度控件
上一步添加了播放開關,還可以在此基礎上添加播放速度的控件來調節播放的快慢
其方法與1.4中添加播放開關的方法類似,其中input的type為range(html 5中新的類型),通過讀取range 的value,將value作為setTimeout的時間參數(作為參數傳入播放方法),
注意:當滑動range,value發生改變時,要使播放停止,再次點擊播放按鈕時,播放方法讀取新的value;
input.id="speedCtrl";
input.type="range";
input.max="1750";
input.min="250";
input.step="250";
input.value="1000";
var i=0;
input.onchange=function(){
pausePlay();
}
總結:
作為一個從學校里剛走出來的非計算機專業的前端新手,實習中的第一次上手項目,就有獨立使用百度地圖API的機會實在幸運。從百度地圖API的具體使用實踐中,我學到了很多,除了百度地圖API以外,還學到了包括prototype、bootstrap(模態框、datetimepicker、validation等插件)等等。
盡管有些不太完善的地方(例如:在infoWindow的content中不能使用bootstrap的模態框等),但百度地圖API的功能仍然十分強大,值得廣大新手學習。特別是隨着移動互聯網的快速發展以及各種帶有gps定位功能的智能設備的爆發式普及,地圖、定位類使用場景越來越多,地圖API的使用需求也將越來越多。
為了更好地練習百度地圖,我打算利用節假日空閑的時間使用百度地圖制作一個小游戲練手,游戲大致構思如下:(未來會在博客中向大家展示!)
1.使用自定義marker作為游戲主角
2.使用自定義控件來操作主角
3.設置關卡或任務,
4.計算獎勵或得分
5.設置障礙
先實現這幾個初級功能需求,就可以使自己的游戲主角在自己的城市中行走了!