您的位置:首页 > 其它

百度地图BMap API的应用实例

2013-11-27 10:47 519 查看

百度地图BMap API的应用实例

分类:
Script 2011-07-14 16:29
5370人阅读 评论(17)
收藏
举报

api百度functioncallbackinputtable

前几天,帮朋友做了几款地图API接口调研,推荐他使用百度BMap和谷歌GMap API,后来又直接交由我来替他做

一来上周帮研究生部老师做的学位证书精准打印系统基本完工,晚上有点时间研究下js

二来去年刚到百度实习头1个月,做的正是js,因此对BMap部分源码、API接口风格以及文档也都有些了解

花了一天两夜,基本功能需求都已经实现(自定义标注、精确和模糊查询、个性化添加、右键菜单等),先贴出效果图:



上图布局,最上面是测试通过的浏览器及其版本,左侧是动态加载的数据源和查询功能,右侧则是调用BMap API实现自己的应用

知识拓展:关于js和css的浏览器兼容性问题,请参见我在百度空间的博客 Javascript 和 CSS 的浏览器兼容总结

设计思路:接口是BMap API,内部功能采用模块化设计,搜索模块、自定义添加、右键菜单事件等,这样设计方便扩展和维护,后期将考虑加入谷歌的GMap

下面,详细介绍内部功能是如何设计和实现的

1、数据源格式

数据源格式是比较规整的,具体格式如下:

[javascript]
view plaincopyprint?

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" } ];

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)

[javascript]
view plaincopyprint?

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);
}

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、精准与模糊查询(正则式实现)

[javascript]
view plaincopyprint?

// 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;
}

// 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、标记查询的结果

[javascript]
view plaincopyprint?

// 标记查询结果
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);
});
})()
}
}

// 标记查询结果
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、右键菜单的实现

[javascript]
view plaincopyprint?

// 添加右键菜单
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

// 添加右键菜单
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)

[javascript]
view plaincopyprint?

<input type="text" name="keyword" id="id_keyword" value="input id" onmousedown="clearKeyword('keyword')" onmouseout="showKeyword('keyword')" />
<input type="text" name="keyword" id="id_keyword" value="input id" onmousedown="clearKeyword('keyword')"
onmouseout="showKeyword('keyword')" />


[javascript]
view plaincopyprint?

// 用户按下鼠标,提示信息清除
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";
}
}

// 用户按下鼠标,提示信息清除
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、左侧查询高亮显示

点击查询小图标后,此栏背景色高亮显示,是用户一目了然



实现代码如下:

[javascript]
view plaincopyprint?

// 点击左侧查询小图标
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);
}

// 点击左侧查询小图标
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高级应用特效
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: