工做時被要求到的,結合百度地圖api作一個動態展現標註變化的組件,要求地圖展現某一天的標註,時間軸要求能夠動態播放每一天的標註變化...而後我就開始coding...前端
若有很差的地方,還請你們指出,我也是小白中的一員,接下來開始正文
git
準備工做:github
申請百度api密鑰(具體方法我也很少寫了,你們應該都會) ajax
瞭解一下百度地圖API的開發指南和類參考文檔(若是嫌麻煩的話 能夠直接看Demo示例)json
// 建立Map實例,設置地圖容許的最小/大級別 var map = this.map; map.centerAndZoom(new BMap.Point(121.365593, 37.528502), 15); // 初始化地圖,用城市名設置地圖中心點 //map.enableScrollWheelZoom(true); //啓用滾輪放大縮小
centerAndZoom(center:Point, zoom:Number) 設計模式
參數解釋:api
Point(lng:Number, lat:Number)
以指定的經度和緯度建立一個地理點座標。數組
zoom:number
地圖縮放級別瀏覽器
結合百度地圖api示例Demo 設置點的新圖標和添加多個點示例 結合一下,就能夠改寫成添加多個地圖標註微信
//編寫自定義函數,建立標註 addMarker: function(point, label, status) { // var marker = new BMap.Marker(point); var myIcon = new BMap.Icon("images/rubbish_" + status + ".png", new BMap.Size(32, 32), { anchor: new BMap.Size(16, 32), //中心點設置 infoWindowAnchor: new BMap.Size(16, 4) //消息框位置5 }); var marker = new BMap.Marker(point, { icon: myIcon }); TimerLine.map.addOverlay(marker); //跳動的動畫 // marker.setAnimation(BMAP_ANIMATION_BOUNCE); marker.setAnimation(BMAP_ANIMATION_DROP); var p = marker.getPosition(); var content = "<table>"; content = content + "<tr><td> 編號:" + label.content + "</td></tr>"; content = content + "<tr><td> 座標:" + p.lng + "," + p.lat + "</td></tr>"; content = content + "<tr><td> 狀態:" + status + "</td></tr>"; content += "</table>"; var infowindow = new BMap.InfoWindow(content); //添加綁定事件 addEvent(marker, 'click', getAttr); function getAttr() { this.openInfoWindow(infowindow); } }
百度地圖標註添加看懂了,接下來就是動態添加標註,而且隨和日期的變化而變化,好比展現垃圾箱的動態變化,8.3號清理了顏色爲綠色,8.6號沒清理爲紅色..
動態:就要使用ajax異步獲取數據
變化:就要使用定時器(setInterval或者 setTimeout)
setInterval 循環調用
setTimeout 延遲調用 1次 具體區別能夠自行百度
動手寫插件
function addEvent(dom, type, fn) { //對於支持DOM2級事件處理程序addeventListener方法的瀏覽器 if (dom.addEventListener) { dom.addEventListener(type, fn, false); } else if (dom.attachEvent) { //對於不支持addEventListener方法但支持attchEvent方法的瀏覽器 dom.attachEvent('on' + type, fn); } else { //對於不支持以上兩種,但支持on+'事件名'的瀏覽器 dom['on' + type] = fn; } } var TimerLine = { data: { containerDiv: 'timerline', //容器盒子id datesDiv:'dates',//日期盒子id btnsDiv:'timerlineBtns', btns: { play: "timerbtn-play", stop: "timerbtn-stop", pre:"timerbtn-pre", next:"timerbtn-next" }, processDiv:'processbar', //進度條div }, protect:{ lock_play:false, lock_stop:false, index_label:1, index_process:0 }, rubbish_datas: [], //用來存儲ajax獲取到的數據 index: 0, //變化的index Interval_label: null, Interval_process:null, map: new BMap.Map("allmap", { minZoom: 14, maxZoom: 20 }), Utils: { //編寫自定義函數,建立標註 addMarker: function(point, label, status) { // var marker = new BMap.Marker(point); var myIcon = new BMap.Icon("images/rubbish_" + status + ".png", new BMap.Size(32, 32), { anchor: new BMap.Size(16, 32), //中心點設置 infoWindowAnchor: new BMap.Size(16, 4) //消息框位置5 }); var marker = new BMap.Marker(point, { icon: myIcon }); TimerLine.map.addOverlay(marker); //跳動的動畫 // marker.setAnimation(BMAP_ANIMATION_BOUNCE); marker.setAnimation(BMAP_ANIMATION_DROP); var p = marker.getPosition(); var content = "<table>"; content = content + "<tr><td> 編號:" + label.content + "</td></tr>"; content = content + "<tr><td> 座標:" + p.lng + "," + p.lat + "</td></tr>"; content = content + "<tr><td> 狀態:" + status + "</td></tr>"; content += "</table>"; var infowindow = new BMap.InfoWindow(content); //添加綁定事件 addEvent(marker, 'click', getAttr); function getAttr() { this.openInfoWindow(infowindow); } }, /** * 地圖標註方法 * 參數: datas:標註物數組{date:"",info:{}} * index:序數(日期) * */ mapSetLabel: function(datas, n,isInterval) { TimerLine.map.clearOverlays(); var index; console.log(TimerLine.protect.index_label); if(isInterval){ TimerLine.protect.index_label++; if (TimerLine.protect.index_label >= TimerLine.rubbish_datas.length - 1) { TimerLine.protect.index_label = TimerLine.rubbish_datas.length - 1; clearInterval(TimerLine.Interval_label); TimerLine.protect.lock_play=false; } } if (n == null) { if(TimerLine.protect.index_label==0){ TimerLine.protect.index_label=1 } index = TimerLine.protect.index_label; } else { index = parseInt(n); TimerLine.protect.index_label = index; } var info = datas[index].info; var info_count=0; var addMarker_Interval=setInterval(function(){ var p = info[info_count].point.split(','); var p_x = parseFloat(p[0].toString()); //緯度 var p_y = parseFloat(p[1].toString()); //經度 //建立label標籤 var label = new BMap.Label(info[info_count].title, { offset: new BMap.Size(20, -10) }); //建立標註點 var point = new BMap.Point(p_x, p_y); //狀態(垃圾箱狀態) var status = info[info_count].status; //添加標註的方法 TimerLine.Utils.addMarker(point, label, status); info_count++; if(info_count>=info.length){ clearInterval(addMarker_Interval); } },0); }, //添加日期點擊事件綁定 dates li click bindEvent: function() { var datesDiv = document.getElementById("dates"); addEvent(datesDiv,'click',function(e){ var event = e || window.e; var target = event.target || event.srcElement; for(var i=0;i<TimerLine.rubbish_datas.length;i++){ if(target.innerText==TimerLine.rubbish_datas[i].date){ // TimerLine.protect.index_process=i; TimerLine.protect.index_label=i; //播放解鎖 if(TimerLine.protect.lock_play) TimerLine.protect.lock_play=false; TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas, i,false); TimerLine.Utils.Setprocess(i,false); return ; } } }) }, //進度條滾動 Setprocess:function(index,isInterval){ if(isInterval){ TimerLine.protect.index_process++; console.log(TimerLine.protect.index_process); console.log(TimerLine.rubbish_datas.length); if(TimerLine.protect.index_process >= TimerLine.rubbish_datas.length-1){ TimerLine.protect.index_process = TimerLine.rubbish_datas.length-1; clearInterval(TimerLine.Interval_process); TimerLine.protect.lock_play=false; } } var datesDiv = document.getElementById("dates"); var processDiv = document.getElementById(TimerLine.data.processDiv); if(index==null){ processDiv.style.width =parseInt(processDiv.style.width)+datesDiv.getElementsByTagName('li')[0].offsetWidth+'px'; }else{ processDiv.style.width =datesDiv.getElementsByTagName('li')[0].offsetWidth*parseInt(index+1)+'px'; } } }, //TimerLine初始化 init: function() { this.createMap(); this.ajaxCreate(); //事件綁定 this.bindEvent(); }, createMap: function() { // 建立Map實例,設置地圖容許的最小/大級別 var map = this.map; map.centerAndZoom(new BMap.Point(121.365593, 37.528502), 15); // 初始化地圖,用城市名設置地圖中心點 //map.enableScrollWheelZoom(true); //啓用滾輪放大縮小 }, ajaxCreate: function() { var That = this; var containerDiv = That.data.containerDiv; $.ajax({ type: "get", url: "js/json.json", dataType: 'json', success: function(data) { containerDiv = document.getElementById(containerDiv); //容器id That.rubbish_datas = data.result.datas; // //console.log(That.rubbish_datas); That.create(containerDiv, That.rubbish_datas); //日期時間綁定 That.Utils.bindEvent(); } }); }, create: function(containerDiv, datas) { var That = this; var datasDiv ='<div class="processcontainer"><div id="processbar" style="width:120px;"></div></div>'; // var datasDiv = '<ul id="dates" class="timerlineul dates clearfix">'; datasDiv += '<ul id="dates" class="timerlineul dates clearfix">'; for (var i = 0; i < datas.length; i++) { datasDiv += '<li>' + datas[i].date + '</li>'; } datasDiv += '</ul>'; document.getElementById(That.data.btnsDiv).innerHTML='<div class="timerline-btns clearfix"><div id="timerbtn-pre" class="iconfont icon-shangyishou"></div><div id="timerbtn-play" class="iconfont icon-zanting"></div><div id="timerbtn-next" class="iconfont icon-xiayishou"></div></div>' //建立第一天的標註 this.Utils.mapSetLabel(datas, 0,false); // console.log(TimerLine.index); That.datas = datas; containerDiv.innerHTML = datasDiv; }, //播放 暫停 委託事件----時間綁定 bindEvent: function() { if (this.data.btns == null) return; var That = this; addEvent(document.getElementById(That.data.btnsDiv), 'click', function(e) { var event = e || window.e; var target = event.target || event.srcElement; //播放事件 if (target.id == That.data.btns.play) { if(!TimerLine.protect.lock_play){ if(TimerLine.protect.index_label >= TimerLine.rubbish_datas.length-1){ TimerLine.protect.index_label=0; var processDiv = document.getElementById(TimerLine.data.processDiv); var datesDiv = document.getElementById("dates"); processDiv.style.width = datesDiv.getElementsByTagName('li')[0].offsetWidth+'px'; } if(TimerLine.protect.index_process >= TimerLine.rubbish_datas.length-1){ TimerLine.protect.index_process=0; } // TimerLine.Interval_label = setInterval("TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas,null,true)", 1000); TimerLine.Interval_process = setInterval("TimerLine.Utils.Setprocess(null,true)",1000); $("#timerbtn-play").attr("class","iconfont icon-zanting1"); //播放枷鎖 TimerLine.protect.lock_play=true; //暫停解鎖 TimerLine.protect.lock_stop=false; }else if(TimerLine.protect.lock_play){ $("#timerbtn-play").attr("class","iconfont icon-zanting"); TimerLine.Interval_label&&clearInterval(TimerLine.Interval_label); TimerLine.Interval_process&&clearInterval(TimerLine.Interval_process); //播放解鎖 TimerLine.protect.lock_play=false; //暫停加鎖 TimerLine.protect.lock_stop=true; } } if(target.id == That.data.btns.pre){ if(TimerLine.protect.index_label==0) return; TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas, TimerLine.protect.index_label-1,false); TimerLine.Utils.Setprocess(TimerLine.protect.index_process-1,false); TimerLine.protect.index_process=TimerLine.protect.index_process-1; } if(target.id == That.data.btns.next){ if(TimerLine.protect.index_label==TimerLine.rubbish_datas.length-1) return; TimerLine.Utils.mapSetLabel(TimerLine.rubbish_datas, TimerLine.protect.index_label+1,false); TimerLine.Utils.Setprocess(TimerLine.protect.index_process+1,false); TimerLine.protect.index_process=TimerLine.protect.index_process+1; } }); } } TimerLine.init();
以上是我本身手寫的組件代碼,對設計模式瞭解仍是通常.原本是想用原型模式寫,不過在setInterval時候,方法無法調用原型方法,讓後我就改爲了單例模式
data:數據容器綁定
protect 保護屬性 (對播放、暫停、時間軸index、標註index)
rubbish_datas 存儲ajax讀取的數據
Interval_label 百度地圖標註定時器
Interval_process 時間軸定時器
Utils 工具類
init() TimeLine初始化
createMap() 建立百度地圖
ajaxCreate() 獲取數據,建立容器(create()),時間綁定(bindEvent())
兩個定時器運行時,公共index 容易讀取錯誤,一個定時器修改了index 另外一個定時器還沒修改,這樣形成了建立標註與當前時間不符合,
注:要將修改公共變量儘可能寫在一個方法中。公共變量最好不要在多個方法中公用,容易在增減的時候出現沒必要要的BUG
定時器運行到最後一天的時候要將定時器清除。
附上預覽地址
更多內容能夠訂閱本人微信公衆號,一塊兒開啓前端小白進階的世界!
不給 Demo 地址 是否是對不起大家。哈哈?
能夠關注微信公衆號 回覆百度地圖時間軸組件 ,便可收到 Demo 的地址。