百度地圖BMap API的應用例項
分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow
也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!
前幾天,幫朋友做了幾款地圖API介面調研,推薦他使用百度BMap和谷歌GMap API,後來又直接交由我來替他做
一來上週幫研究生部老師做的學位證書精準列印系統基本完工,晚上有點時間研究下js
二來去年剛到百度實習頭1個月,做的正是js,因此對BMap部分原始碼、API介面風格以及文件也都有些瞭解
花了一天兩夜,基本功能需求都已經實現(自定義標註、精確和模糊查詢、個性化新增、右鍵選單等),先貼出效果圖:
上圖佈局,最上面是測試通過的瀏覽器及其版本,左側是動態載入的資料來源和查詢功能,右側則是呼叫BMap API實現自己的應用
知識拓展:關於js和css的瀏覽器相容性問題,請參見我在百度空間的部落格 Javascript 和 CSS 的瀏覽器相容總結
設計思路:介面是BMap API,內部功能採用模組化設計,搜尋模組、自定義新增、右鍵選單事件等,這樣設計方便擴充套件和維護,後期將考慮加入谷歌的GMap
下面,詳細介紹內部功能是如何設計和實現的
1、資料來源格式
資料來源格式是比較規整的,具體格式如下:
var data = [ { id: 100, point: "116.397128|39.916527", addr: "紫金天子城", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 101, point : "116.422792|40.009471", addr: "十里村", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 202, point: "116.484289|39.97936", addr: "楊家大灣", mainFlow: 13, subFlow: 19.9, press: 14, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 303, point: "116.454494|39.964011", addr: "趙鵬", mainFlow: 3, subFlow: 69.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 404, point: "116.394601|39.987925", addr: "王店", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 500, point: "116.469899|39.87684", addr: "劉村", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 501, point: "116.331292|39.949031", addr: "西子營", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 602, point: "116.374561|39.894302", addr: "馬甲鎮", mainFlow: 13, subFlow: 19.9, press: 14, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 703, point: "116.419527|39.945374", addr: "大牛集市", mainFlow: 3, subFlow: 69.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 804, point: "116.394601|39.987925", addr: "小牛峽灣", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" }, { id: 905, point: "116.368099|39.942332", addr: "徐家水庫", mainFlow: 3, subFlow: 169.9, press: 4, voltage: 13.3, flashFlow: 1, isEle: "有市電", time: "2011-7-13 16:30:00" } ];
目前資料來源採用的text文字格式進行儲存與載入,隨著需求和應用的擴大,後期將會使用MySQL資料庫進行儲存與提取
2、動態載入資料來源(左側table)
function init_MiddleLeft() { var top_div = document.getElementById("id_middle_left"); var table = document.createElement("table"); table.setAttribute("border", 1); table.setAttribute("width", 280); for (var i = 0; i < data.length; i++) { var tr = document.createElement("tr"); var td = document.createElement("td"); var str = data[i].id; var msg = document.createTextNode(str); td.appendChild(msg); tr.appendChild(td); td = document.createElement("td"); str = data[i].addr; msg = document.createTextNode(str); td.appendChild(msg); tr.appendChild(td); td = document.createElement("td"); var img = document.createElement("img"); img.src = "./info.gif"; img.value = this.data[i]; img.onclick = function(){return click(this)}; // img.onclick=Function("click(this.value)"); td.appendChild(img); tr.appendChild(td); table.appendChild(tr); } top_div.appendChild(table); }
左側動態載入資料來源效果圖:
3、精準與模糊查詢(正則式實現)
// search類原型 function searchClass(data) { this.datas = data; } // 設定資料來源 searchClass.prototype.setData = function (data) { this.datas = data; } // 去掉字串空格 searchClass.prototype.trim = function (str) { if (null == str) { str = ""; } else { str = str.toString(); } return str.replace(/(^[\s\t\xa0\u3000]+)|([\u3000\xa0\s\t]+$)/g, ""); } // search原型查詢模組 // rule = {id: "id", key: "keyword", query: "single|more", show: "one|all"} searchClass.prototype.search = function (rule) { if (null == this.datas) { alert("資料來源不存在!"); return false; } if ("" == this.trim(rule) || "" == this.trim(rule.id) || "" == this.trim(rule.key) || "" == this.trim(rule.query)) { alert("請指定要搜尋內容!"); return false; } var reval = []; // 返回值,object陣列型別 var datas = this.datas; // search類,成員變數 me = this; // 全域性this,getData中me // 新增查詢結果 var addData = function (data) { reval.push(data); } // 獲取查詢資料來源串 var getData = function (data, id) { var _id = me.trim(id); var d = "data"; if (0 == _id.length) { return data; } else { d += '["' + _id + '"]'; return eval(d); } } // 檢索遍歷 for (var i = 0; i < datas.length; i++) { var data = datas[i]; var d = getData(data, rule.id); var dReg = new RegExp(this.trim(rule.key)); if ("one" == rule.show) { // 顯示查詢標記 if ("single" == rule.query && d == rule.key) { // 精準查詢(single) addData(data); } else if ("more" == rule.query && dReg.test(d)) { // 模糊查詢(正則式實現) addData(data); } } else if ("all" == rule.show) { // 顯示全部標記 addData(data); } } // 返回結果 return reval; }
4、標記查詢的結果
// 標記查詢結果 window.addMarker = function (data_a) { map.clearOverlays(); // 首先清理已有標記 // 遍歷查詢結果資料(data_a) for (var i = 0; i < data_a.length; i++) { // 獲取座標(經度、緯度),在地圖map上顯示 var px = data_a[i].point.split("|")[0]; var py = data_a[i].point.split("|")[1]; var point = new BMap.Point(px, py); var marker = new BMap.Marker(point); map.addOverlay(marker); //marker.enableDragging(true); // 生成標記資訊(table) var content = "<table>"; content = content + "<tr><td> 裝置編號:" + data_a[i].id + "</td></tr>"; content = content + "<tr><td> 安裝地點:" + data_a[i].addr + "</td></tr>"; content = content + "<tr><td> 主表流量:" + data_a[i].mainFlow + "</td></tr>"; content = content + "<tr><td> 副表流量:" + data_a[i].subFlow + "</td></tr>"; content = content + "<tr><td> 管網壓力:" + data_a[i].press + "</td></tr>"; content = content + "<tr><td> 裝置電壓:" + data_a[i].voltage + "</td></tr>"; content = content + "<tr><td> 瞬時流量:" + data_a[i].flashFlow + "</td></tr>"; content = content + "<tr><td> 有無市電:" + data_a[i].isEle + "</td></tr>"; content = content + "<tr><td> 記錄時間:" + data_a[i].time + "</td></tr>"; content += "</table>"; // 捕獲標記點選事件,並且顯示資訊 // 函式閉包,總是執行 (function () { var infoWindow = new BMap.InfoWindow(content); marker.addEventListener("click", function () { this.openInfoWindow(infoWindow); }); })() } }
標記效果圖:
5、右鍵選單的實現
// 新增右鍵選單 var contextMenu = new BMap.ContextMenu(); var txtMenuItem = [ { text: "放大", callback: function () { map.zoomIn() } }, { text: "縮小", callback: function () { map.zoomOut() } }, { text: '檢視北京', callback: function () { map.centerAndZoom("北京") } }, { text: '放置到最大', callback: function () { map.zoomTo(18) } }, { text: '獲取改點座標', callback: function(p){ var px = p.lng; var py = p.lat; alert("該點座標:\n經度:" + px + "; \n緯度:" + py); } }, { text: '新增該店標註', callback: function (p) { var marker = new BMap.Marker(p), px = map.pointToPixel(p); map.addOverlay(marker); marker.enableDragging(true); } } ]; // 遍歷選單items,新增進選單 for (var i = 0; i < txtMenuItem.length; i++) { contextMenu.addItem(new BMap.MenuItem(txtMenuItem[i].text, txtMenuItem[i].callback, 100)); if (i == 1 || i == 3) { contextMenu.addSeparator(); } } map.addContextMenu(contextMenu); // 新增選單到map
選單效果圖:
6、模糊查詢結果
左側,輸入“1”,模糊匹配查詢和顯示查詢結果
右側,輸出3個標記結果
校驗:100、101、501三項,都含有查詢關鍵字"1“,查詢結果正確
7、關注細節,改善體驗
在實現過程中,也考慮了一些細節處理,這裡舉兩個示例
a、輸入框自動提示
當用戶沒有輸入時,輸入框顯示提示資訊"input id",當用戶滑鼠點選後,提示資訊自動清除(是不是很像AJAX的水印效果 哈哈)
其實,其內部實現也不復雜,但不經意的設計,體現的卻是很人性化
具體實現(onmousedown和onmouseout)
<input type="text" name="keyword" id="id_keyword" value="input id" onmousedown="clearKeyword('keyword')" onmouseout="showKeyword('keyword')" />
// 使用者按下滑鼠,提示資訊清除 function clearKeyword(keyword) { var input = document.getElementsByName(keyword); input[0].value = ""; // 清除提示 } // 滑鼠移走,如果內容為空,則重新提示 function showKeyword(keyword) { var input = document.getElementsByName(keyword); var value = input[0].value; if ("" == value) { // 判斷是否為空 input[0].value = "input id"; } }
b、左側查詢高亮顯示
點選查詢小圖示後,此欄背景色高亮顯示,是使用者一目瞭然
實現程式碼如下:
// 點選左側查詢小圖示 function click(obj) { // 先清理所有td元素,擦除上次高亮顯示腳印 var td_a = document.getElementsByTagName("td"); for (var i = 0; i < td_a.length; i++) { td_a[i].setAttribute("bgcolor", "#ffffff"); } // 高亮標記本次查詢資訊 obj.parentNode.setAttribute("bgcolor", "#ff0000"); var data_a = []; var data = obj.value; data_a.push(data); addMarker(data_a); }
好啦,就到這裡
後期計劃,想把谷歌的地圖API也擴充套件進來,實現百度和谷歌地圖自由選擇
再有時間的話,將會嘗試加入更新、更酷的技術,打造一些HTML5和CSS3高階應用特效