百度地图JavaScript API是一套由JavaScript语言编写的应用程序接口,它能够帮助您在网站中构建功能丰富、交互性强的地图应用,包含了构建地图基本功能的各种接口,提供了诸如本地搜索、路线规划等数据服务。
1、包含功能
基本地图功能、地图控件展示功能、覆盖物功能、工具类功能、定位功能、右键菜单功能、鼠标交互功能、图层功能、本地搜索功能等等。
2、基础需求
- 希望大家有一定的html+css基础
- 希望大家有一定的JavaScript基础
为大家讲解在去哪儿网中用到了哪些百度地图的API,如何实现去哪儿网效果。
AK的获取
JavaScript API在新版本引入ak机制。JavaScript API v1.4及以前版本无须申请密钥
点我进入 找到申请密钥并注册为百度开发者找到申请密钥并注册为百度开发者
进入创建应用页面
IP白名单处建议大家就填0.0.0.0/0,方便在不同的电脑上操作
创建好后大家就能获得自己的AK了
开发内容简介
我们将利用百度地图的地图控件展示功能、覆盖物功能、工具类功能、定位功能、本地搜索功能实现如下图效果:
课程将带你一点一点完成图中的内容,大家加油。
基础布局
我们将实现页面的基础的HTML+DIV布局
1、tab效果布局
由于需要做切换效果,我们需要将筛选条件、酒店列表两列对应的内容区域设置position为absolute,并设置其中之一为隐藏,同时我们要将筛选条件下的checkbox所在div隐藏,当点击时才会见到选项。
2、js加载数据布局
此外我在酒店列表对应内容中并未写入酒店内容,因为这些重复的东西我们可以通过ajax获取数据,用js写入
最后我们要得到的效果如图:
由于课程主要意图不在于讲布局,所以本章只会简略的解释一下布局,望见谅。
<!DOCTYPE HTML> <html> <head> <meta charset="utf-8"/> <title>map</title> <script src="./js/map.js" type="text/javascript"></script> <script src="./js/jquery.min.js"></script> <script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=rpfl5y7smpwmTnY4CCYLBbvtrjSGRaR6"> </script> <script type="text/javascript" src="http://api.map.baidu.com/library/SearchInfoWindow/1.5/src/SearchInfoWindow_min.js"></script> <link rel="stylesheet" type="text/css" href="./js/map.css"> <link rel="stylesheet" href="http://api.map.baidu.com/library/SearchInfoWindow/1.5/src/SearchInfoWindow_min.css" /> </head> <body> <div class="container clearfloat"> <div class="select-cont"> <div class="menu clearfloat"> <div id="sidebar-filter" class="select">筛选条件</div> <div id="sidebar-hotel">酒店列表</div> </div> <div class="scroll-clip"> <div id="list"> <ul> <li> <span>价格范围</span> <div> <input type="checkbox" value="0,200" class="price">200以下 <input type="checkbox" value="200,300" class="price">200-300 <br/> <input type="checkbox" value="300,500" class="price">300-500 <input type="checkbox" value="500,3000" class="price">500以上 </div> </li> <li> <span>酒店级别</span> <div> <input type="checkbox" value="1" class="type">经济型 <input type="checkbox" value="2" class="type">二星级 <br/> <input type="checkbox" value="3" class="type">三星级 <input type="checkbox" value="4" class="type">舒适四星级 <br/> <input type="checkbox" value="5" class="type">高档五星级 </div> </li> </ul> </div> <div id="hotel"> <div class="clearfloat hotel"> <dl> <dd><img src="{{imgSrc}}"/></dd> <dt>{{name}}</dt> <dt>{{address}}</dt> <span class="price">{{price}}</span> </div> </div> </div> </div> <div id="map-cont"></div> </div> </body> </html>
*{ margin: 0px; padding: 0px; -webkit-box-sizing: border-box; box-sizing: border-box; font-family: 微软雅黑, 宋体; } .title{ height: 86px; text-align: center; font-size: 24px; line-height: 86px; } .clearfloat:after{ content: ""; display: block; clear: both; } .select-cont{ width: 298px; float: left; } .menu{ background-color: #3cb0d0; width: 100%; padding: 5px 5px 0; color: white; } .menu>div{ float: left; width: 144px; height: 32px; line-height: 32px; text-align: center; font-size: 16px; cursor: pointer; } .select{ background-color: white; color: black; } .scroll-clip{ width: 100%; height: 253px; position: relative; border: 1px solid #eee; } #list,#hotel{ position: absolute; width: 100%; height: 100%; overflow-y: scroll; color: #49484b; text-align: center; } #list::-webkit-scrollbar,#hotel::-webkit-scrollbar { width: 8px; height: 8px; background-color: #F5F5F5; } #list::-webkit-scrollbar-track,#hotel::-webkit-scrollbar-track { -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3); border-radius: 0px; background-color: #F5F5F5; } #list::-webkit-scrollbar-thumb,#hotel::-webkit-scrollbar-thumb { border-radius: 10px; -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3); background-color: #555; } #list ul li{ display: block; cursor: pointer; font-size: 16px; line-height: 58px; border-bottom: #EEEEEE 1px solid; } #list ul li span{ display: block; } #list ul li div{ line-height: 28px; margin-bottom: 10px; text-align: left; display: none; } #list ul li div input{ margin-left: 30px; } #hotel { display: none; } #hotel div{ padding: 10px; } #hotel div dl{ display: block; width:190px; border-bottom: 1px #eee solid; float: left; } #hotel div span{ display: block; color: red; float: right; text-align: left; } #hotel div dl dd{ float: left; width: 46px; background-color: #f9f9f9; margin-right: 8px; text-align: center; height: 46px; } #hotel div dl dd img{ width: 100%; height: 100%; } #hotel div dl dt{ float: left; text-align: left; line-height: 24px; width: 135px; overflow:hidden; white-space:nowrap; text-overflow:ellipsis; cursor: pointer; } #hotel div dl dt:last-child{ font-size: 8px; } #hotel div:hover dl dt{ color: #37B9FF; } #map-cont{ position: absolute; width:380px; height:290px; margin-left: 298px; }
//后续课程将实现js的tab切换效果 window.onload = function() { var list = document.getElementById(’list’); var hotel = document.getElementById(’hotel’); //var hote2 = document.getElementsByName(’menu clearfloat’); list.style.display = ’none’; hotel.style.display = ’block’; //??? }
百度地图的引入
这一节我们将学习如何引入百度地图。
1、BMap.Map(“container”)
创建一个地图实例,其中container指容器id,之后需要调用Map.centerAndZoom()方法对地图进行初始化。未进行初始化的地图将不能进行任何操作。
2、BMap.Point
以指定的经度和纬度创建一个地理点坐标。
3、map.centerAndZoom(center:Point, zoom:Number)
初始化地图,他有种设置参数方式,一是center类型为Point时,zoom必须赋值,范围3-19级,还有就是如果center类型为字符串时,比如“北京”,zoom可以忽略,地图将自动根据center适配最佳zoom级别。
window.onload = function(){ var map = new BMap.Map("map-cont"); var point = new BMap.Point(116.404, 39.915); map.centerAndZoom(point, 15); }
js实现
这一节我们将实现菜单栏的tab切换效果。
1、js实现tab切换
通过用js对筛选条件、酒店列表两个选项所在div绑定点击事件,点击后将本选项对应的内容显示,将另外一个选项对应div隐藏
对应代码如下
sidebar_filter.onclick = function () { list.style.display = ’block’; sidebar_filter.className = ’select’; sidebar_hotel.className = ’’; hotel.style.display = ’none’; }; sidebar_hotel.onclick = function () { list.style.display = ’none’; sidebar_hotel.className = ’select’; sidebar_filter.className = ’’; hotel.style.display = ’block’; };
2、js点击展开选项栏
原理相同,只是我们这次使用for循环对span的点击事件进行绑定,并为每个选项加入clicked属性,标记是否已经展开,如果已经展开再点击则收起。
for(var i=0;i<list_li.length;i++){ list_li[i].clicked = false; list_li[i].onclick = function(){ var div = this.getElementsByTagName(’div’); if(this.clicked){ div[0].style.display = ’none’; this.clicked = false; } else{ div[0].style.display = ’block’; this.clicked = true; } } }
同样js动画不是本课程重点,因此只能简述原理,感兴趣的小伙伴可以去找相应的课程学习
js加载数据
这一小节我们将使用js完成酒店列表内容
1、数据获取
我们要通过ajax获取LBS.云中的数据并将对应的旅馆数据加载到,右侧选项中,并且每次对条件修改的同时我们将异步刷新旅馆列表界面,这里我们仅需完成旅馆信息加载函数。我将会在后面小节中介绍LBS云的内容。
2、获取模板
我们使用下面代码,将hotel中的内容获取
var hotel = document.getElementById(’hotel’); var hotel_html = hotel.innerHTML;
3、正则表达式的使用
我们匹配到hotel_html中的{{id}}、{{imgSRC}}等等,并将其替换为我们想要的数据。做法如下:
var html = ’’; for(var i=0;i<hotelInfo.length;i++){ html += hotel_html.replace(/{{imgSrc}}/g,hotelInfo[i].img.big) .replace(/{{name}}/g,hotelInfo[i].name) .replace(/{{address}}/g,hotelInfo[i].address) .replace(/{{price}}/g,’?’+hotelInfo[i].price); }
我将获取hotelInfo的函数放到了loadInfo.js文件夹中,我们将在将LBS那一章时讲解。
window.onload = function() { var sidebar_filter = document.getElementById(’sidebar-filter’); var sidebar_hotel = document.getElementById(’sidebar-hotel’); var list = document.getElementById(’list’); var hotel = document.getElementById(’hotel’); var list_li = list.getElementsByTagName(’li’); var list_span = list.getElementsByTagName(’span’); var hotel_html = hotel.innerHTML; for(var i=0;i<list_li.length;i++){ list_span[i].clicked = false; list_span[i].index = i; list_span[i].onclick = function(){ var div = list_li[this.index].getElementsByTagName(’div’); if(this.clicked){ div[0].style.display = ’none’; this.clicked = false; } else{ div[0].style.display = ’block’; this.clicked = true; } } } sidebar_filter.onclick = function () { list.style.display = ’block’; sidebar_filter.className = ’select’; sidebar_hotel.className = ’’; hotel.style.display = ’none’; }; sidebar_hotel.onclick = function () { list.style.display = ’none’; sidebar_hotel.className = ’select’; sidebar_filter.className = ’’; hotel.style.display = ’block’; }; var url = ’http://api.map.baidu.com/geosearch/v3/nearby?ak=ir7jFwBM0tPkLebXl3ScT9cB&geotable_id=135736&location=116.395884,39.932154&radius=100000’ getHotelInfo(url,function(err,hotelInfo){ hotel.innerHTML = ’’; if(!err){ var html = ’’; for(var i=0;i<hotelInfo.length;i++){ html += hotel_html.replace(/{{imgSrc}}/g,hotelInfo[i].img.big) .replace(/{{name}}/g,hotelInfo[i].name) .replace(/{{address}}/g,hotelInfo[i].address) .replace(/{{price}}/g,’¥’+hotelInfo[i].price); } //获取到的html赋值给hotel.innerHTML hotel.innerHTML = html; } }); }
地图配置
这一小节我们将完成对地图的配置,为地图加入拖拽、滚轮缩放功能。
1、简介
百度地图提供许多配置方法,地图拖拽、滚轮放大缩小、双击放大、键盘操作等等,我们将为我们的地图配置启用滚轮放大缩小、启用双指操作缩放、启用地图拖拽。
2、默认开启的地图配置
百度地图默认开启了地图拖拽、双击放大、双指操作缩放、自动适应容器尺寸变化自动适应容器尺寸变化。
3、配置开启关闭操作
我们只需要调用例如map.enableDragging()开启地图拖拽功能,map.disableDragging()禁用地图拖拽。更多相关函数可以查看官方API中的配置方法栏。
4、配置开启滚轮放大缩小
我们只需要加入’map.enableScrollWheelZoom();’即可
window.onload = function() { var sidebar_filter = document.getElementById(’sidebar-filter’); var sidebar_hotel = document.getElementById(’sidebar-hotel’); var list = document.getElementById(’list’); var hotel = document.getElementById(’hotel’); var list_li = list.getElementsByTagName(’li’); var list_span = list.getElementsByTagName(’span’); var hotel_html = hotel.innerHTML; //地图加载 var map = new BMap.Map("map-cont",{enableMapClick:false}); var point = new BMap.Point(116.404, 39.915); map.centerAndZoom(point, 15); //??? map.enableScrollWheelZoom(); //事件绑定 for(var i=0;i<list_li.length;i++){ list_span[i].clicked = false; list_span[i].index = i; list_span[i].onclick = function(){ var div = list_li[this.index].getElementsByTagName(’div’); if(this.clicked){ div[0].style.display = ’none’; this.clicked = false; } else{ div[0].style.display = ’block’; this.clicked = true; } } } sidebar_filter.onclick = function () { list.style.display = ’block’; sidebar_filter.className = ’select’; sidebar_hotel.className = ’’; hotel.style.display = ’none’; }; sidebar_hotel.onclick = function () { list.style.display = ’none’; sidebar_hotel.className = ’select’; sidebar_filter.className = ’’; hotel.style.display = ’block’; }; //数据加载 function insertData(err,hotelInfo){ hotel.innerHTML = ’’; if(!err){ var html = ’’; for(var i=0;i<hotelInfo.length;i++){ html += hotel_html.replace(/{{imgSrc}}/g,hotelInfo[i].img.big) .replace(/{{name}}/g,hotelInfo[i].name) .replace(/{{address}}/g,hotelInfo[i].address) .replace(/{{price}}/g,’¥’+hotelInfo[i].price); } hotel.innerHTML = html; } } var url = ’http://api.map.baidu.com/geosearch/v3/nearby?ak=ir7jFwBM0tPkLebXl3ScT9cB&geotable_id=135736&location=116.395884,39.932154&radius=100000’ getHotelInfo(url,function(err,hotelInfo){ insertData(err,hotelInfo); }); }
控件使用
这一小节我们将为地图添加上平移缩放控件。
1、控件的简介
百度地图为我们提供了许多控件平移缩放(NavigationControl)、比例尺(ScaleControl)、缩略地图
(OverviewMapControl)、地图类型(MapTypeControl)、版权(CopyrightControl等等,在这一节,我将为
地图添加平移缩放控件。
2、向地图添加控件
我们需要为我们的地图添加平移缩放控件
map.addControl(new BMap.NavigationControl(opts));
3、很多时候我们需要改变控件位置,那么该怎么办呢?
有两种方式,在讲解两种方式之前我们需要对对Size这个类进行讲解
我们可以使用Size(width:Number, height:Number)的方式构造出一个Size对象,width代表水平方向数值,height代表垂直方向数值。
4、设置控件位置的方式
1)在构造对象时对位置进行设置,我们可以使用通过传入一个对象参数构造控件对象
这个对象中有anchor和offset属性共同控制控件在地图上的位置。
其中anchor允许的值为:
BMAP_ANCHOR_TOP_LEFT 表示控件定位于地图的左上角。
BMAP_ANCHOR_TOP_RIGHT 表示控件定位于地图的右上角。
BMAP_ANCHOR_BOTTOM_LEFT 表示控件定位于地图的左下角。
BMAP_ANCHOR_BOTTOM_RIGHT 表示控件定位于地图的右下角。
注意Size中的width,height是以anchor为参照的。
使用方式:
例如:
new BMap.ScaleControl({offset:new BMap.Size(100, 100)})
</code>
</p>
<p>
2)可以使用<em>setAnchor(anchor)</em>和<em>setOffset(offset:Size)</em>设置
例如:
</p>
<pre class="sh_javascript">var navigationControl = new BMap.NavigationControl();
navigationControl.setAnchor(BMAP_ANCHOR_TOP_LEFT);
navigationControl.setOffset(new BMap.Size(20,20));
map.addControl(navigationControl);
覆盖物的基础操作
这一节我们将学习覆盖物的种类以及如何添加、删除、隐藏覆盖物
1、覆盖物的种类
Marker(标注表示地图上的点)Label(表示地图上的文本标注)Polyline(表示地图上的折线)Polygon(表示地图上的多边形)Circle(表示地图上的圆)
InfoWindow:信息窗口也是一种特殊的覆盖物,它可以展示更为丰富的文字和多媒体信息。注意:同一时刻只能有一个信息窗口在地图上打开。
2、覆盖物的添加和删除
我们可以使用map.addOverlay方法向地图添加覆盖物,使用map.removeOverlay方法移除覆盖物,注意这种方法并不适合InfoWindow。
我们以Marker为例
var marker = new BMap.Marker(point); map.addOverlay(marker); //map.removeOverlay(marker)删除覆盖物marker //map.clearOverlays();删除覆盖物
3、覆盖物的显示与隐藏
覆盖物的显示和隐藏分别用到了show,hide两个函数
同样以marker为例
var marker = new BMap.Marker(point); map.addOverlay(marker); marker.hide();//显示覆盖物 //marker.show();隐藏覆盖物
为地图批量添加标注
这一节我们将在地图上标出我们获取的到旅馆位置
1、原理
我们可以通过for循环的方式为地图批量添加标注
2、设置点的新图标
我们可以通过Icon(url:String, size:Size[, opts:IconOptions])函数构造出一个Icon对象并且我们能通过setImageSize(offset:Size)改变图标大小,
再通过marker的setIcon(icon:Icon)将图标加载到地图上去
想要改变图标的小伙伴们可以自己尝试改变图标,在课程中我仅使用默认图标,见谅
例如:
var marker = new BMap.Marker(point); map.addOverlay(marker); marker.setAnimation(BMAP_ANIMATION_DROP); var icon = new BMap.Icon("/course/56e1378eecba4b4d31cd2ba5/img/c3_3.jpg", new BMap.Size(50,100)); icon.setImageSize(new BMap.Size(50,100)); marker.setIcon(icon);
3、批量添加标注
我们只需要对获取到的hotelInfo进行循环即可
function addMarker(point){ var marker = new BMap.Marker(point); map.addOverlay(marker); } getHotelInfo(url,function(err,hotelInfo){ insertData(err,hotelInfo); if(!err) { for (var i = 0; i < hotelInfo.length; i++) { var point = new BMap.Point(hotelInfo[i].location[0],hotelInfo[i].location[1]); addMarker(point); } } });
将标注添加到地图上
window.onload = function() { var sidebar_filter = document.getElementById(’sidebar-filter’); var sidebar_hotel = document.getElementById(’sidebar-hotel’); var list = document.getElementById(’list’); var hotel = document.getElementById(’hotel’); var list_li = list.getElementsByTagName(’li’); var list_span = list.getElementsByTagName(’span’); var hotel_html = hotel.innerHTML; //地图加载 var map = new BMap.Map("map-cont",{enableMapClick:false}); var point = new BMap.Point(116.404, 39.915); map.centerAndZoom(point, 15); map.enableScrollWheelZoom(true); var navigationControl = new BMap.NavigationControl(); navigationControl.setOffset(new BMap.Size(20,20)); map.addControl(navigationControl); //事件绑定 for(var i=0;i<list_li.length;i++){ list_span[i].clicked = false; list_span[i].index = i; list_span[i].onclick = function(){ var div = list_li[this.index].getElementsByTagName(’div’); if(this.clicked){ div[0].style.display = ’none’; this.clicked = false; } else{ div[0].style.display = ’block’; this.clicked = true; } } } sidebar_filter.onclick = function () { list.style.display = ’block’; sidebar_filter.className = ’select’; sidebar_hotel.className = ’’; hotel.style.display = ’none’; }; sidebar_hotel.onclick = function () { list.style.display = ’none’; sidebar_hotel.className = ’select’; sidebar_filter.className = ’’; hotel.style.display = ’block’; }; //数据加载 function insertData(err,hotelInfo){ hotel.innerHTML = ’’; if(!err){ var html = ’’; for(var i=0;i<hotelInfo.length;i++){ html += hotel_html.replace(/{{imgSrc}}/g,hotelInfo[i].img.big) .replace(/{{name}}/g,hotelInfo[i].name) .replace(/{{address}}/g,hotelInfo[i].address) .replace(/{{price}}/g,’¥’+hotelInfo[i].price); } hotel.innerHTML = html; } } function addMarker(point){ var marker = new BMap.Marker(point); map.addOverlay(marker); } var url = ’http://api.map.baidu.com/geosearch/v3/nearby?ak=ir7jFwBM0tPkLebXl3ScT9cB&geotable_id=135736&location=116.395884,39.932154&radius=100000’ getHotelInfo(url,function(err,hotelInfo){ insertData(err,hotelInfo); if(!err) { for (var i = 0; i < hotelInfo.length; i++) { var point = new BMap.Point(hotelInfo[i].location[0],hotelInfo[i].location[1]); //??? addMarker(point); } } }); }
自定义覆盖物
这一小节我们需要用自定义覆盖物实现鼠标滑过右侧宾馆选项时出现的宾馆信息
要创建自定义覆盖物,您需要做以下工作:
1)定义一个自定义覆盖物的构造函数,通过构造函数参数可以传递一些自由的变量,这里我们传入一个的旅馆信息。
2)设置自定义覆盖物对象的prototype属性为Overlay的实例,以便继承覆盖物基类。
3)实现initialize方法,当调用map.addOverlay方法时,API会调用此方法,在此方法中我们生成一个div并将图片价格地址等信息引入,可以在css属性框为其写入你想要的样式。
4)实现draw方法,我们在此方法中绘制div并设置div出现的位置。
代码如下:
function ComplexCustomOverlay(point,hotelInfo){ this._point = point; this._hotelInfo = hotelInfo; } ComplexCustomOverlay.prototype = new BMap.Overlay(); ComplexCustomOverlay.prototype.initialize = function(map){ this._map = map; var div = this._div = document.createElement("div"); div.style.position = "relative"; div.style.zIndex = BMap.Overlay.getZIndex(this._point.lat); div.className = ’hotelInfo clearfloat’; div.innerHTML = ’<img src="’+this._hotelInfo.img.big+’"/> <div class="name">’+this._hotelInfo.name+’</div> <div class="address">’+this._hotelInfo.address+’</div> <span class="price">’+’?’+this._hotelInfo.price+’</span>’; div.style.backgroundColor = "white"; div.style.width = ’220px’; div.style.height = ’54px’; map.getPanes().labelPane.appendChild(div); return div; }; ComplexCustomOverlay.prototype.draw = function(){ var map = this._map; var pixel = map.pointToOverlayPixel(this._point); this._div.style.left = pixel.x - 55 +"px"; this._div.style.top = pixel.y + 3 + "px"; };
信息窗口
这一小节我们将实现创建信息窗口以及点击标注出现信息窗口。
1、简介
信息窗口在地图上方的浮动显示HTML内容。信息窗口可直接在地图上的任意位置打开,也可以在标注对象上打开(此时信息窗口的坐标与标注的坐标一致)。 您可以使用InfoWindow来创建一个信息窗实例,注意同一时刻地图上只能有一个信息窗口处于打开状态。
2、信息窗口的创建
我们通过BMap.InfoWindow(content, opts)函数创建一个信息窗口,content可以是HTML内
容opts是一个包含width、height、maxWidth、offset、title、enableAutoPan(是否开启信息窗口打开时地图
自动移动)、enableCloseOnClick(是否开启点击地图关闭信息窗口)、enableMessage(是否在信息窗里显示短信发送按钮)、
message(自定义部分的短信内容)属性的对象。
var sContent =’<div class="infoWindow"><img src="’+hotel.img.big+’" /><div class="clearfloat">’+’<span>’+hotel.name+’</span>’+’<span>’+hotel.price+’</span>’+’</div>’ +’<a>查看详情</a>’+’</div>’+ ’</div>’; var opts = { maxWidth:250px } var infoWindow = new BMap.InfoWindow(sContent,opts);
3、为标注绑定点击打开信息窗口事件
我们需要改造一下addMarker函数,将hotel信息传入,在加入标注时绑定事件,并加入创建信息窗口prodInfoWindow函数
function prodInfoWindow(hotel){ var sContent =’<div class="infoWindow"><img src="’+hotel.img.big+’" /><div class="clearfloat">’+’<span>’+hotel.name+’</span>’+’<span>’+’?’+hotel.price+’</span>’+’</div>’ +’<a>查看详情</a>’+’</div>’+ ’</div>’; var infoWindow = new BMap.InfoWindow(sContent); return infoWindow; } function addMarker(hotel){ var marker = new BMap.Marker(new BMap.Point(hotel.location[0],hotel.location[1])); map.addOverlay(marker); marker.addEventListener(’click’, function () { var infoWindow = prodInfoWindow(hotel); this.openInfoWindow(infoWindow); }) }
事件基础
这一小节我们将学习事件的概念、监听、和移除。
1、事件的概述
百度地图API拥有一个自己的事件模型,我们可监听地图API对象的自定义事件,使用方法和DOM事件类似。注意,百度地图API事件是独立的,与标准DOM事件不同。
2、事件监听
百度地图事件包括地图加载完成事件、地图单击、双击、鼠标移动、拖拽事件,以及添加控件添加覆盖物事件等等
3、事件的参数
百度地图API在事件监听函数中传递事件对象e,每个e参数至少包含事件类型(type)和触发该事件的对象(target)。 API还保证函数内的this指向触发(同时也是绑定)事件的API对象。
除了上一小节我们用到的为标注绑定点击事件,我们还可以看一个简单的获取point案例
var pointInfo = document.getElementById(’pointInfo’); map.addEventListener("click", function(e){ showInfo(e); }); function showInfo(e){ pointInfo.innerHTML = ’鼠标点击处point:’+’(’+e.point.lng+’,’+ e.point.lat+’)’; }
4、事件的移除
事件的移除只需要使用map.removeEventListener()函数即可
map.removeEventListener("click", showInfo);
为宾馆选项绑定鼠标滑过事件
这一小节我们需要实现当鼠标移入选项时在相应宾馆标注下发显示自定义覆盖物,鼠标移出时移除覆盖物功能。
原理
功能实现简单,前面我们已经介绍了自定义覆盖物,只需要用for循环为每个选项绑定onmouseover和onmouseout事件,鼠标移入生成自定义覆盖物,移出则移除覆盖物。
function addListen(hotelInfo){ var hotelI = document.getElementsByClassName(’hotel’); for(var i=0 ; i<hotelI.length; i++) { hotelI[i].myCompOverlay = new ComplexCustomOverlay(new BMap.Point(hotelInfo[i].location[0], hotelInfo[i].location[1]), hotelInfo[i]); hotelI[i].onmouseover = function () { map.addOverlay(this.myCompOverlay); }; hotelI[i].onmouseout = function () { map.removeOverlay(this.myCompOverlay); }; } }
为标注绑定鼠标滑过事件
这一小节我们将实现滑过标注出现自定义覆盖物功能。
1、实现原理
为标注绑定鼠标滑过事件与上一节原理相同,但是有点不同的是我们同时还为标注绑定了鼠标点击事件,为了避免滑过后点击出现信息栏和自定义覆盖物同时存在,我们需要在点击时加入移除覆盖物事件。
2、改造addMarker函数
我们只需在标注添加时为其绑定鼠标事件
function addMarker(hotel){ var marker = new BMap.Marker(new BMap.Point(hotel.location[0],hotel.location[1])); map.addOverlay(marker); marker.addEventListener(’click’, function () { map.removeOverlay(myCompOverlay); var infoWindow = prodInfoWindow(hotel); this.openInfoWindow(infoWindow); }); marker.addEventListener(’mouseover’,function(){ myCompOverlay = new ComplexCustomOverlay(new BMap.Point(hotel.location[0],hotel.location[1]), hotel); map.addOverlay(myCompOverlay); }); marker.addEventListener(’mouseout’,function(){ map.removeOverlay(myCompOverlay); }); }
这样我们地图算是完成大半,大家加油.
LBS云简介
这一小节我们将了解一些LBS云相关内容。
1、简介
LBS.云是百度地图针对LBS开发者推出的平台级服务,结合已有的地图API和SDK服务,通过开放服务端存储和计算能力,提供海量位置数据的实时存储、检索、展示一体化解决方案。
2、LBS名称解释
1)位置数据表(geotable):百度LBS云提供给开发者自定义存储一类位置数据的集合,我们后面小节中的geotable_id就是下图创建按钮右方括号中内容。
2)自定义扩展列(column):对应下图中的字段,注意保留字段有
ak,sn,callback,latitude,longitude,coord_type,city_id,id,title,address:,tags:,location,create_time,modify_time,geotable_id,type,weight,distance,city,province,district
3)位置数据(poi)即为开发者在定义好属性和扩展列的位置数据表里面中带有位置属性的业务数据记录,类似与常见数据表下的一条记录
3、LBS后台
如上图所示,LBS云和数据库类似,你可以在建表,插入字段,插入数据,编辑图标样式,我们的数据就存在LBS云中
LBS云检索
这一小节我们将学习怎么使用LBS云检索
1、LBS云检索分类
LBS云检索分为poi周边检索和、poi本地检索、poi矩形检索、poi详情检索,四者都是通过get请求获取LBS云中数据
1)poi周边检索
周边检索是指以一点为中心(中心点通过location参数指定),搜索中心点附近指定距离范围(搜索半径通过radius参数指定)内的POI点。
Url格式:http://api.map.baidu.com/geosearch/v3/nearby 2)poi本地检索
本地检索是指可检索指定区域范围内的poi信息,区域通过region参数来设定
Url格式:http://api.map.baidu.com/geosearch/v3/local 3)poi矩形检索
矩形检索是指可检索指定矩形范围内的poi信息,检索区域通过bounds参数设定的矩形的左下角和右上角的经纬度坐标来确定
Url格式:http://api.map.baidu.com/geosearch/v3/bound 4)poi详情检索
通过poi点的id来检索poi点详情
Url格式:http://api.map.baidu.com/geosearch/v3/detail/{uid}
2、检索参数
我们已经看过了各种检索的URL格式。但是我们还需要通过不同参数筛选我们需要的数据。例如:
这个URL搜索以“116.395884,39. 932154”为中心,1000米范围内价格在200到300的饭店,并将搜索结果按照距离和价格的升序排序。
注意:geotable_id可以在LBS云后台位置数据表获取
在官方文档已经给出了各种参数含义,我们要做的是通过云检索得到我们想要的数据,下一节,我将介绍通过ajax获取LBS云中的数据。大家加油。
LBS云检索获取数据
这一小节我将带大家搞定getHotelInfo函数
1、请求参数
整个课程都是以
以“116.395884,39. 932154”为中心10000米范围内为基础进行筛选的,大家可以根据在LBS云中的数据进行修改。
2、通过ajax请求获取数据
我们通过发送ajax跨域请求,获取数据,我们采用的datatype是jsonp,我们获取到的数据如下图
我们需要将contents中的内容取出,如果没有获取到数据,我们将返回相应信息,具体代码如下:
function getHotelInfo(url,next){ var hotelInfo = []; $.ajax({ type:’get’, url:url, dataType:’jsonp’, success:function(data){ var hotel={}; console.log(data); if(data.contents){ for(var i=0;i<data.contents.length;i++){ hotel={}; hotel.address = data.contents[i].address; hotel.name = data.contents[i].title; hotel.price = data.contents[i].price; hotel.type = data.contents[i].type; hotel.img = data.contents[i].img; hotel.location = data.contents[i].location; hotelInfo.push(hotel); } next(null,hotelInfo); } else{ next(data.message); } } }); }
麻点图的使用
这一小节我将介绍麻点图的基础使用
1、不使用标注的原因
标注不适用于大量数据,数据较多时用标注会使地图加载速度变慢,因此我们需要采用麻点图来代替标注。
2、CustomLayer构造函数
CustomLayer构造函数可以通过接收数据存储空间id(geotable id)参数生成用户数据图层,存储空间id可以在创建数据存储时获得。其中参数和LBS云中用法相同,相信大家也了解了。
var customLayer=new BMap.CustomLayer({ geotableId: ***, //geotable id q: ’’, //检索关键字 tags: ’’, //空格分隔的多字符串 filter: ’’ //过滤条件 });
3、addTileLayer函数
使用
map.addTileLayer(customLayer);
添加用户自定义图层
4、编写prodTileLayer函数
如果地图有customLayer图层,就将其移除,再生成新的customLayer图层
function prodTileLayer(filter){ if(customLayer) { map.removeTileLayer(customLayer); } customLayer=new BMap.CustomLayer({ ak:’rpfl5y7smpwmTnY4CCYLBbvtrjSGRaR6’, geotableId: 135736, q: ’’, //检索关键字 tags: ’’, //空格分隔的多字符串 filter: filter //过滤条件 }); map.addTileLayer(customLayer); }
麻点图的使用
这个小节我们将介绍searchInfoWindow并为麻点图绑定点击事件
1、引入文件
为用户绑定麻点图层点击事件,我们需要使用searchInfoWindow,我们必须引入文件
<script type="text/javascript" src="http://api.map.baidu.com/library/SearchInfoWindow/1.5/src/SearchInfoWindow_min.js"></script>
2、searchInfoWindow的使用
使用方式与InfoWindow相似,具体参数如下
searchInfoWindow = new BMapLib.SearchInfoWindow(map, content, { title : "百度大厦", //标题 width : 290, //宽度 height : 105, //高度 panel : "panel", //检索结果面板 enableAutoPan : true, //自动平移 searchTypes :[ BMAPLIB_TAB_SEARCH, //周边检索 BMAPLIB_TAB_TO_HERE, //到这里去 BMAPLIB_TAB_FROM_HERE //从这里出发 ] });
3、创建prodprodInfoWindow函数
我们可以创建一个与prodInfoWindow函数类似的prodprodInfoWindow函数生成searchInfoWindow
function prodSearchInfoWindow(hotel){ var sContent =’<div class="infoWindow"><img src="’+hotel.img.big+’" /><div class="clearfloat">’+’<span>’+hotel.title+’</span>’+’<span>’+’?’+hotel.price+’</span>’+’</div>’ +’<a>查看详情</a>’+’</div>’+ ’</div>’; var infoWindow = new BMapLib.SearchInfoWindow(map,sContent,{ panel : "panel", //检索结果面板 enableAutoPan : true, //自动平移 searchTypes :[] }); return infoWindow; }
4、绑定点击事件
我们只需要为customLayer绑定hotspotclick事件即可
customLayer.addEventListener(’hotspotclick’,function(e){ var customPoi = e.customPoi;//poi的默认字段 var contentPoi=e.content;//poi的自定义字段 var searchInfoWindow = prodSearchInfoWindow(contentPoi); var point = new BMap.Point(customPoi.point.lng, customPoi.point.lat); searchInfoWindow.open(point); });
5、改写prodTileLayer函数
为麻点图绑定点击事件。
function prodTileLayer(filter){ if(customLayer) { map.removeTileLayer(customLayer); } customLayer=new BMap.CustomLayer({ ak:’ir7jFwBM0tPkLebXl3ScT9cB’, geotableId: 135736, q: ’’, //检索关键字 tags: ’’, //空格分隔的多字符串 filter: filter //过滤条件 }); map.addTileLayer(customLayer); customLayer.addEventListener(’hotspotclick’,myHotspotclick); }
为checkbox绑定事件
这一小节我们将用js为为checkbox绑定事件,并学会如何判断checkbox是否处于选中状态
1、获取所有的checkbox
var checkbox = document.getElementsByTagName(’input’);
2、for循环绑定点击事件,通过元素的checked属性判断是否选中
for(var i=0;i<checkbox.length;i++){ checkbox[i].onclick = function(){ if(this.checked){ //相应的操作 } else{ //相应操作 } } }
生成filter
这一节我们将介绍实现数据筛选至关重要的生成filter函数
1、filter函数的用处
生成filter,可用于麻点图数据筛选,还可以用来生成url异步获取LBS云数据
2、require对象的构建
我们构建一个require对象,我们用他来保存用户需求,并且加入了获取最大值最小值以及删除数组元素的函数,方便对数据进行操作。
var require = { price:[], type:[], getMax: function () { var max = Math.max.apply(null, this.price); return max; }, getMin: function(){ var min = Math.min.apply(null, this.price); return min; }, removeEle: function(index,arrName){ if(index>-1){ this[arrName].splice(index,1); } } };
3、为点击事件加入相应操作
我们为每个checkbox加入data-label属性。
我们使用getAttribute(’data-label’)获取checkbox的自定义data-label数据,这个数据用来标记数据是价格相关还是酒店类型相关。
每次点击我们都需要更新require中的相应内容,如选择type时,我们将对应的type添加到数组中,当取消选择时我们又将对应的type从数组中移除。
for(var i=0;i<checkbox.length;i++){ checkbox[i].onclick = function(){ if(this.checked){ switch (this. getAttribute(’data-label’)){ case ’price’:{ var price = (this.value).split(’,’); require.price.push(parseInt(price[0]),parseInt(price[1])); break; } case ’type’:{ require.type.push(parseInt(this.value)); break; } } } else{ switch (this. getAttribute(’data-label’)){ case ’price’:{ var price = (this.value).split(’,’); var index = require.price.indexOf(parseInt(price[0])); require.removeEle(index,’price’); var index = require.price.indexOf(parseInt(price[1])); require.removeEle(index,’price’); break; } case ’type’:{ var index = require.type.indexOf(parseInt(this.value)); require.removeEle(index,’type’); break; } } } } }
4、生成filter
通过require的内容生成filter,需要注意的是用户没有选择时我们加载所有数据这种情况
function getFilter(require){ var filter = ’’; if(require.price[0] === 0 || require.price[0]){ var price = ’price:’ + require.getMin() + ’,’ +require.getMax(); filter += price; } console.log(require.type.length); var type = require.type.length !==0 ? ’|hotel_type:[’+ require.type.join(’,’)+’]’ :’’; filter += type; return filter; }
异步刷新地图
最后一小节我们将完成地图编写的最后一步刷新地图
每次点击checkbox我们需要刷新两个区域,一是宾馆选项,二是地图。
1)我们需要通过getFilter函数获取filter
2)通过map.removeTileLayer移除图层,再加入新图层,我们直接使用prodTileLayer函数
3)用filter拼凑出url,通过ajax获取旅馆信息(使用getHotelInfo函数)
4)用insertData刷新旅馆并为它绑定事件
function refreshPage(filter){ var url = ’<a href="http://api.map.baidu.com/geosearch/v3/nearby?ak=ir7jFwBM0tPkLebXl3ScT9cB&geotable_id=135736&location=116.395884,39.932154&radius=100000">http://api.map.baidu.com/geosearch/v3/nearby?ak=ir7jFwBM0tPkLebXl3ScT9cB&geotable_id=135736&location=116.395884,39.932154&radius=100000</a>’ if(filter) { prodTileLayer(filter); url = url + ’&filter=’ + filter; } else{ prodTileLayer(’’); } getHotelInfo(url,function(err,hotelInfo){ if(err){ console.log(err); insertData(err); } else { insertData(null,hotelInfo); addListen(hotelInfo); } }); }