监一- 。r FORUM OF EXPERTS 一 - ., 。 . , 。:。. 百度地图API应用数例 朱根荣 摘要:使用地图API获取地理坐标、获取路径或区域边界的地理坐标数据、获取公交、自驾线 路信息、在地图上添加标注、实现图文结合、互动。 关键词:百度地图:API应用 百度地冈API免费开放,无需申请key(v1.5以前),在线 调用方便,开发文档详尽,广为网站应用。文中以介绍秀洲党 校相关地理信息为例,对百度地图API在网站建设中的应用作 了一些探讨。 1 图文交互需求 在用文字介绍地理信息的同时,配之于地图,当用户在文 字区将光标移到某个地理要素(地名、道路、区域)名称上时, 在地图上显示相应的标注,光标离开即隐藏。一可给人于动 感,二可对相应地理要素形成直观的印象。 如介绍秀洲党校地理位置的文字为“秀洲党校位于嘉兴 老城区中心,南临市区主十道中山路,西傍传统商业街建国 路……”。希望是: (1)打开该网页时,以醒目的标记标注“秀洲党校”的位 置,当光标移到“秀洲党校”文字上时,标注产生一动画效果 f如闪烁、变色、淡入淡出等)。 (2)光标移到“嘉兴老城区”几字上时,显示嘉兴老城区 区域.从而凸显党校在嘉兴市区的位置。光标离开时,隐藏该 区域。 (3)当光标移到“中山路”或“建国路”的等文字上时, 分别显示中山路或建国路,离开时隐藏之。 2 准备工作 要实现上述功能.首先要在网页上添加地图;其次需获取 地址、道路、区域的地理数据;i是将地址、道路、区域等在 地图上标注出来;四是建立文字与地图的相互联系,形成图文 互动。 2.1 在网页上添加地图 (1)将百度地图APl导入网页: <script src= http://api.map.baidu.com/api?v=1.4”type=” text/javascript”></script> (2)布局网页。采用两列布局,左列显示文字,右列显示 地图,两列均用<div>元素定位,其id属性分别为divText, divMap。 (3)创建并加载地图: vat map; //全局变量,表示将创建的地图实例 ¥(function0{IoadMap0;}); //网页打开时加载地图 function IoadMap0{ map=new Bmap.Map(“divMap”) map.centerAndZoom(datas[0],1 4): ) 函数loadMap 0为网页<body> ̄素load事件的处理函数, 使网页一打开即加载地图。甬数中第一行,创建一个地图实 例,并显示在id为divMap中<div>元素中;第二行调整地图的 中心点和放大级数,其中datas[O】为秀洲党校的地理坐标点 (后面说明),14为缩放级数,API规定此值在3—18之间。 2_2获取地址的地理坐标 已知地名,且百度地图数据库中有此地名,可用地址解析 类Geoeode的getPoint 0方法,其原型为:getPoint(address, callback,city1。在已创建地图实例map的情况下,可通过以下 代码,在网页上显示某地址的标注及地理坐标(经、纬度): var geo=new BMap.Geocoder0; geo.getPoint(“地址IItpointGot,"嘉兴市”): function p0jntGOt《pojnt){ var s output=S(“#divResult“): if(point){ map.centerAndZoom(point 1 6) map.addOverlay(new BMap.Marker(point)); //添加该地址的标注 s=”(__+ (point.Ing).toFixed(6)+“,”+ (point.1at).toFixed(6)+”)“: //该地址的经、纬度 output.htmI(s): )else{ output.htm 没有找到!”) ) ) 脑螭程2建0巧13与.鲡23挚 29 I】 … ’ ’’ 实用第一 智慧密集 .. 代码中的“divResult”为网页上以此为id的一个<div>元素。 如果上述方法无法获取,则可用单击取点法。先为地图实 例添加鼠标单击事件侦听器: map addEventListener(“click”,showPoint);//添力口鼠标单 ∥击事件侦听器 map.setDefauItCurs0 crosshair”) ://设置地图上 ,/的光标样式为十字 然后,在事件处理函数中,借助于单击事件参数,获取单 击位置的地理坐标点: function showPoint(e){ var s=“(“+ (e point.Ing).toFixed(6)+“.“+ (e.point.1at).toFixed(6)+“)“: ∥单击位置的经、纬度 ¥《”#divResult“).html(s); ) 2.3获取路径的地理坐标数组 如果所需路径是一条道路,则可在该道路上取两点f地理 坐标点1,用获取驾车路线方案的类DrivingRoute的Se ̄FCh方法 获取: 如: var drv=new BMap.DrivingRoute(map,{onSearchCom plete:getPoints": drv.search(start.end); ∥以下是搜索完成的回调函数,参数results是搜索结果 function getPOints(results){ var plan=results getPlan(O);/厥第一个行车方案 va r route=plan.getRoute(O);脓该方案中的第一条线路 var arr=route.getPathO;//获取该线路的地理坐标点数组 ∥在地图上画出该线路 map.addOverlay(new BMap.Polyline(arr, {strokeColor: #O030ff",strokeOpacity:0.5 strokeWeight:4,enableMassClear:true})); map.setViewport(arr); //调整视野 ∥在网页上显示该线路上各点的经、纬度 var S= ‘ for(var i=O;i<arr.1ength;i++){ s+:”</br>( +arr[i].Ing+”, +arr[i].1at+ )“: } ¥(“#divResult“).html(s); } 复制所输出的各点经、纬度,粘贴到iS文件中,即可组成 该路径的坐标点数组。如果所求路径不是一条道路,或上述方 法所获取的路径不是所求的,那只有用原始的单击取点法,在 路径的每个转折处单击,获取每个转折点的地理坐标。 2.4获取区域边界的地理坐标点数组 如果所求区域是一个县级或以上的行政区域.则可用行政 区域边界类Boundary的get 0方法。如: function getArea(name){ 30电 嚣与雏 ∥参数name为行政区域的名称 lf(!name)return; var bound=new BMap.Boundary(); bound.get(name,boundGot); //获取行政区域边界 ) //以下是get方法的回调函数,参数results为行政区域边 ,/界坐标点数组 function boundGot(resuIts){ var result=document.getElementByld(“divResult“): result.innerHTM L=“ : 讦(!results){ result.innerHTML=”未找到!“: return; } var count=results.boundaries.1ength;//区域个数 var s=III1 5stmp for(var i=O i<c0unt:i++){ 脏地图上画第j个区域 var po Lygon=new BMap PoIygon(resuIts.boundaries[i], (strokeWeight:1.strokeColor:”blue”, strokeSt,/le:。。dashed”, fillColor:“#f2f4ff",fillOpacith:O.5)): map.add0VerIay《pofygon): strop=results.boundaries[i]; //第i个区域的坐标点字符串 stmp=stmp.replace(/;/g,"<br/>“): //替换分隔符, //使每个坐标点一行 s+=stmp;//将第i个区域的坐标点添加到字符串中 ) ¥(“#divResult”).html(s); 腧出坐标点数组 map.setViewport(polygon.getPathO);//调整视野 } 如所求区域不是县级及以上的行政区域,则需另觅它法: 如单击取点法,行政区域组合法(长三角),路径组合法(嘉兴 老城区1。 通过这些方法,即可获取文字描述中各地址、道路、区域 的地理坐标点、地理坐标点数组,为便于调用,将其按在文字 中出现的次序放在一个数组datas中,保存于一个名为 mapdata.js文件中。另外,再建一个全局数组marks.用于存放 各标注f或覆盖物)的引用。 3应用举例 3.1 标注党校的地理位置 为了使网页打开时,即可在地图上看到“秀洲党校”的标 注,还需在loadMap函数(2.1)中添加几行,以创建该标注: marks[O]=new Bmap.Marker(data[O]); map.addOverlay(marks[O]); 如此添加标注,虽然简便,但难免形式单一,信息量少, 一-一 FORUMOFEXPERTS 一 r …… - 可用以下方法之一改进: (1)自定义标注图标 var icn=new Bmap.Icon(“images/dh.gif“,new Bmap.Size (20,2O)) marks[O】.setlcon(icn); 其中,dh.gif是一幅保存于images目录下的20x20的党徽 图片 (2)为标注添加标签 var lab=new BMap.Label(”标签内容“.{offset:new Bmap. Size(20,一2O))) marks[O].setLabe…ab): 这里的“标签内容”可以是纯文本,也可以是html文本, 后者如:“<img alt='dh SIC= images/dh.giF style='verticle-align: middle'/><span style='color:red >秀洲党校</span>”。 Offset:为标签相对于标注点的偏移量。 (3)使用开源库BMapLib中的富标注类RichMarker marks【0】=new Bm apLib.RichMarker(“内容”,datas【0L{¨ anchor“:new BmapSize(一40,一20))): 这里的“内容”同上款一样,既可为纯文本,也可为html 文本。当然要使用此类,需下载该类的源代码,并将其引用到 网贞。假设下载后保存在当前网站的js/RichMarker.js,则应 在<head>标签后添加: <script type=”text/javascript“src= js/RichMarker.js“><,Script> (4)自定义覆盖物类CustomOverlay CustomOverlay继承自Overlay类,其构造函数是: CustomOverlay(postion,text1,text2,type),如: var text1.text2; text1=“<img alt= dh src= images/dh.gif style= verticle- align:middle'/><span style= color:red >秀洲党校</span>”: text2= 嘉兴市秀洲区委党校</br/>中山东路133号” marks[O]=new CustomOverlay(data[O],text1,text2,1): map.addOverlay(marks[O]); 当然,要用CustomOverlay类,也需引入该类的源代码, 即在<head>标签后添加 <script type=‘‘text/javascript“src=。。js/CustomOverlay js。 。></script> 3.2介绍党校周边环境 假设介绍文字为: “秀洲党校位于嘉兴老城区中心,南临 市区主干道中山路,西傍传统商业街建国路,商务区的江南 大厦、戴梦得购物中心步行数分钟即至。”为了让地图动态地显 示文字中划线的地理要素,先将划线的文字置于<span>元素中: <b id=”xzdx“>秀洲党校</b> <span id=“area一1”>嘉兴老城区</span> <span id=”route_2“>中山路</span> 这里<span>元素id的命名除第第一个秀洲党校“xzdx” 外,其余包含两个部分,用下划线分隔,前面部分表示类型, 分别取point(地点)、route(路径)、area(区域)、scen(景点), 后面部分是在描述文字中出现的序号,对应mapdata.js文件中 datas数组的索引。 接下来,为<b>、<span>元素绑定事件处理函数。先让鼠 标在“秀洲党校”文字上时,让相应标注闪烁: //为<b id=“xzdx“>元素绑定鼠标在其上的事件处理函数 ¥(“#xzdx“).mouseover(f¨ckMark); //以下为该事件的处理函数,每隔200毫秒让“秀洲党校”标注显 ∥示/隐藏一次 function flickMark(e){ var idlntv n=0,elem=¥(this); elem.o钎(): dlntv=setInterval(fIick ng,200); function flicking(){ n++: if(n>6){ clearInterval(idlntv); marks[O].show(); mark.mouseoverffIickMark); return; } if(marks[O].isVisibleO)marks[O].hide(); else marks[O].show(); ) 】 再为<span> ̄素绑定在鼠标上、鼠标离开的事件处理函数: ¥(”span”).mouseover(showMark); ¥flslpan“).mouseout(removeMark); 相应的事件处理函数为: //鼠标在<span> ̄素上时,在地图上显示相应的覆盖物 function showMark()f var id,arr,type,ind; id=¥(this).attr(“id”): //获取鼠标所在元素的jd _fl!id)return; arr=id.split(“一”): if(arr.1ength<2)return;//2U果鼠标在<span id=“xzdx”>,则返回 type=arr[O],ind=arr[1】: ∥从id中提取类型和编号 switch(type){ 艮据类型确定显示什么样的覆盖物 case ‘point“: showPoint(ind,¥(this).html《)): break; case”route”: showRoute(ind); break; case“area”: showArea(ind); break; case”scen”: //用于显示市区主要景点 showScen(ind); 2013.23 脑绋趣箍圬与舔护 、’ 实用第一 智慧密集 break; ) ) //鼠标离开<span>时,清除覆盖物 function removeMark(e){ var id,arr; id=¥(this).attr( id”): if(!id)return; arr=id.split(ii—ii,,. map.removeOverlay(marks[arr[1】】)= hideDist0; ) //显示地点 function showPoint(ind,adrName){ var html=”<div style= wldth:60px:te×t—aIign:center >“ +adrName+“</div>”: marks[ind]=new CustomOverlay(datas[ind],html,htmI 1) map.addOverlay(marks[ind]); map.setViewport([datas[0],datas[ind]]); ) ∥显示路径 function showRoute(ind){ marks[ind】=new BMap.PolyIine(datas【ind】, {strokeColor:”blue”,strokeWeight:6,stroke0pacity:O.3}): map.addOverlay(marks[ind]); map.setViewport(datas[ind]); } //显示区域 function showArea(ind)( marks[ind]=new BMap.Polygon(datas【ind】, {strokeWeight:1,strokeColor:“#0000ff",strokeStyle:“dashed“, fillColor:”#c3dfea",fillOpacity:O.5}】 圭立多边形覆盖物 map.addOverlay(marks[ind]); map.setViewport(datas[ind]); ) 3.3描述党校便利的市内交通 假设描述文字如下: 交通十分便捷,距风景秀丽的南湖圣地仅1.6公里车 程,至南湖新渡El 3.7公里,至火车站车程仅1.2公里,至 火车南站(高铁站)车程仅12.7公里,至汽车北站车程3.4公 里,至汽车南站f客运中心)车程9.5公里。 只需用类似<span id=”route 6”>南湖圣地</span>的 语句将划线文字置于<span>元素中。id中的前半部分相同,均 取route,后半部分编号依次为6、7、8、9、10、11。事件的 绑定及事件处理函数同例2。 3.4描述所在城市的位置及区位优势 描述文字:嘉兴市位于浙江省东北部、长江三角洲杭嘉湖 平原腹心地带,是长江一角洲重要城市之一。东临东海+南 倚钱塘江,北负太湖,两接天目之水,大运河纵贯境内。市 32电电脑螭程技巧与维 品与维 城处于江、海、湖、河交会之位,扼太湖南走廊之咽喉,与 沪、杭、苏、湖等城市相距均不到百公里,区位优势明显,尤 以在人间天堂苏杭之间著称。 这里“嘉兴市”、“东海”、“钱塘江”、 “太湖”相应< span>元素的id的前半部分为point, “浙江省”、 “长江 角 洲”相应<span>元素的id的前半部分为area,其余为route, 后半部分编号依次为是12—22。 3_5显示市区主要景点 文字区显示为: 南湖景 :狮子汇、小瀛洲、南湖、湖心岛、烟雨楼、会 景园、纪念馆、揽秀同、壕股塔f伍相祠)。 古运河畔:… 相应的HTML代码如下: <div id=”desc3”> 南湖景区 pa d=“scen一0”>狮子汇</span> pa d=“scen一1“>/J、瀛渺l'I</span> pa d=“scen一2”>南湖</span> pa d=“scen_3“>湖心岛</s;pan> </div> 这里用单击事件进行交互。不仅希望在单击上述景点名称 时.在地图上标注出该景点的位置.而且还希望看到该景点的 一幅或多幅罔片以及该景点的简要介绍。多幅图片以左右滑动 方式呈现。百度地图API虽没有提供该项功能,但可借助于 “信息窗口”实现。具体步骤如下: (1)搜集各景点的图片保存于scens目录下。 (2)创建一个景点对象数组seen,数组中的每个元素表示 一个景点对象,该对象有以下属性: title:景点名称 position:景点的地理位置,数据类型为BMap.Point desc:景点描述 pics:景点图片文件名数组 names:景点图片简要说明数组 鉴于该数组内容较多,单独存放于文件scenery.js中。 (3)创建一个滑动显示图片的网页slidePies.htm(这离题 较远,不赘述).该网页带一个参数ind,表示景点序号。 (4)在景点名称上单击的事件处理函数showScen 0.该函 数接收一个参数ind为景点序号,其核心是创建并显示百度地 图的信息窗口,这个信息窗口的内容是以slidePics.htm为源文 件的<iftame>: function showScen(ind){ map centerAndZoom(scen[ind]position,1 6): var src=“”: src= SlidePhoto.htm?ind=”+ind; ’ ’ 『 “l h 。J 1 。l ’ 实用第一 智慧密集 _ ,】 , 。J j … 【。 J L 【f_ ,, l1 r , ^,J … } l“}(- H {function poIicyChange(ind){ var policys=【BMAP DRIVlNG POLICY LEAST TIME, BMAP DRIVING POLICY LEAST DISTANCE BMAP , DRlVIN_getDuration(true): ¥(”<td colspan= 2 ></td>”) .addClass(”tdt“).css(“padding-right","4px”) htmI(s).appendTo(tr); G POLICY AVOlD HIGHWAYS]; .,/获取用户输入的起点地址 var start=S(“#txtStaG”).valO; //获取每个关键步骤,并以表格形式输出到页面 for(var i=O:i<route.getNumSteps0;i++){ ∥获取用于输出的div元素,并清空其中的内容 var resultdiv=¥(“#drvResult“).empty(): if(!driving) driving=new BMap.DrivingRoute(map,{renderOptiOns: var step=route.getStep(i); tr=¥(”<tr>“).attr(”idnIIItr”+i) .addClass(”tr“).click(showStep(route,step,1)) appendT0(tab): .{map:map,autoViewport:true}}): ¥(“<td>“).addClass(”tdl”).htmI((i+1)+“.“).appendTo(tr) driving.clearResults0; //清除搜索结果 ¥(“<td>“).addClass(“td2“) .driving.setPoIicy(po1icys【ind】): ∥搜索完成的回调函数 //设置行车策略 html(step.getDescription()) driving.setSearchCompleteCallback(searchDriveCompleted); .appendTo(tr); ) ) ) driving.search(start,“秀洲党校“)://调用search()方法,开始搜索 } ,/搜索完成的回调函数 function searchDriveCompleted(results){ 4 结语 事实上,还可以添加行车路线中的每一步文字描述与地图 的交互,即在某一步的文字描述上单击时,在地图上显示这一 if《driving.getStatus()==BMAP—STATUS—SUCCESS){ //获取第一条方案 var plan=results.getPlan(O); //获取方案的驾车线路 var route=plan.getRoute(0); var resuttdiv=¥(“#drvResult“).addClass( drv“): 步的具体路线,甚至还可以在地图上给出一个信息窗口,这个 信息窗口不仅提供这一步的具体描述,还可以提供“上一步”、 “下一步”两个按钮,单击之,使地图显示上一步(下一步)的 路径及相关说明。 (收稿日期:20l3—08—30) var tab=S(“<table>“).addClass(“table“).appendTo(resultdiv): var tr=¥(“<tr>“).addClass(“tr0“).appendTo(tab): var S=“全程:“+plan.getDistance《true)--I”,。+plan (上接第28页) { //返回将target串中首个与pattern匹配的子串删除后的字符串 public static MyString deleteFirst《MyString target, MyString pattern) { int i=target.inde×Of(pattern): if(i一1) return target; 4实现效果 简单介绍了用BF算法和KMP算法实现的字符串匹配与查 找功能。限于篇幅,控件界面编程方面不再赘述。匹配与查找 操作演示如图7所示。 return target.substring(0,i)+target.subst ring(i+pattern.1ength()) ) ∥返回将target串中所有与pattern匹配的子串删除后的字符串 public static String delete AIl(St g target,String pattern) { int i=target.inde×Of(pattem); while(_l=一1) { target=target.substring(0,i)+target.substring(i+pattern.1ength()) i=target.indexOf(pattern,i): ) return target; 图7基于BF与KMP算法的匹配与查找 (收稿日期:2013—09—25) ) 34电 盆与维