1. 简介
地理位置一般有经度(南北极的连接线)和纬度(东西连接的线)描述。HTML5中提供Geolocation API(地理位置应用程序接口)用于获取用户的地理位置(即定位)。通过Geolocation较准确知道浏览器用户当前位置。
为获取用户的地理位置信息,需要使用多中方式,主要的方式有:IP地址,GPS全球定位系统,Wi-Fi无线网络,基站。
不同的方式对位置精确度是不一样的。对于桌面浏览器,通常使用WiFi(误差20米),或者IP位置(这受城市的档次影响,会出错)。对于手机设备倾向于使用GPS(误差10米,只能在户外使用),WiFi或者是基站(由运营商的基站位置决定,误差约1000m)。
2. 浏览器支持
Internet Explorer 9、Firefox、Chrome、Safari 以及 Opera 支持地理定位。
注释:对于拥有 GPS 的设备,比如 iPhone,地理定位更加精确。
3. 地理定位:
1)在使用地理位置对象前,首先检测浏览器是否支持定位,测试如下
if(navigator.geolocation){
//如果该浏览器支持,则navigator.geolocation返回true
}else{
//不支持地理定位
}
2)单次定位:getCurrentPosition(successCallback,errorCallback,options)
getCurrentPosition用于获取一次用户的地理位置信息,该函数接收三个参数,其中
第一个参数为:请求成功回调的函数(success:function(position){}),请求成功后的地理位置信息通过参数传递给回调函数,在返回的位置对象中,position对象中具有:
– 请求成功函数
– 经度 : position.coords.longitude
– 纬度 : position.coords.latitude
– 准确度 : position.coords.accuracy
– 海拔 : position.coords.altitude
– 海拔准确度 : position.coords.altitudeAcuracy
– 行进方向 : position.coords.heading,设备正北顺时针前进的方位
– 地面速度 : position.coords.speed,设备外部环境的移动速度(m/s)
– 时间戳 : newDate(position.timestamp),当位置捕获到时的时间戳
上面这些属性中只有coords.latitude,coords.longitude和coords.accuracy一定会有值返回的,至于其他属性很可能返回的就是null。
第二个参数为:请求失败回调的函数(error:function(err){ }),可选
» 失败编号 :err . code
» 0 : 不包括其他错误编号中的错误
» 1 : 用户拒绝浏览器获取位置信息
» 2 : 尝试获取用户信息,但失败了
» 3 : 设置了timeout值,获取位置超时了
第三个参数为:设置的额外参数,以键值对的形式设置,可选,可以设置三个参数:enableHighAccuracy, timeout, maximumAge.其中:
enableHighAccuracy参数表示是否高精度可用,为Boolean类型,默认为false,如果开启,响应时间会变慢。
timeout参数表示等待响应的最大时间,默认是infinity,表示无穷时间。
maximumAge表示应用程序的缓存时间。单位毫秒,默认是0,意味着每次请求都是立即去获取一个全新的对象内容。
注意:发起定位时,浏览器默认不允许用户进行定位,在弹出的询问窗中主动要允许定位。
使用举例:
<inputtype="button"value="开始定位"id="btn"/>
<divid="box"></div>
<script>
varoInput=document.getElementById("btn");
varoBox=document.getElementById("box");
//点击按钮时发起定位
oInput.οnclick=function(){
//判断浏览器是否支持地理定位
if(navigator.geolocation){
//如果支持,则发起定位
navigator.geolocation.getCurrentPosition(function(pos){
//定位成功后回调的函数,位置信息以参数的形式传给该函数
console.log('经度:'+pos.coords.longitude);
console.log('纬度:'+pos.coords.latitude);
oBox.innerHTML+='<p>经度:'+pos.coords.longitude+'<br/>纬度:'+pos.coords.latitude
+'<br/>精确度:'+pos.coords.accuracy+'<br/>海拔:'+pos.coords.altitude
+'<br/>海拔准确度:'+pos.coords.altitudeAccuracy
+'<br/>时间:'+pos.timeStamp
+'</p>'
},function(err){
//定位失败后回调的函数,错误的结果以参数的形式传给该函数
alert(err.code);
},{
//设置的额外参数,可选参数
enableHighAccuracy:true,
maximumAge:100,
timeout:5000
});
}
}
</script>
获取时需要允许浏览器能够获取位置
3)多次定位:watchPosition(successCallback,errorCallback,options)
getCurrentPosition返回用户的当前位置,并继续返回用户移动时的更新位置(就像汽车上的 GPS),该函数的使用和getCurrentPostion完全一样,参数几乎一致(但是第三个参数选项中,添加了一个一个新的参数:frequency更新的频率),每次返回的结果也一致。
如果需要停止定位,使用clearWatch()-停止 watchPosition()方法。clearWatch方法值接受一个参数,这是参数是由watchPosition方法返回的watchID
使用举例:
<inputtype="button"value="开始定位"id="btn"/>
<inputtype="button"value="停止定位"id="stop"/>
<divid="box"></div>
<script>
varoInput=document.getElementById("btn");
var oBox=document.getElementById("box");
//停止按钮
varstopGeo=document.getElementById("stop");
var wacthId=null;
//点击按钮时发起定位
oInput.οnclick=function(){
//判断浏览器是否支持地理定位
if(navigator.geolocation){
//如果支持,则发起定位
wacthId=navigator.geolocation.watchPosition(function(pos){
//定位成功后回调的函数,位置信息以参数的形式传给该函数
console.log('经度:'+pos.coords.longitude);
console.log('纬度:'+pos.coords.latitude);
oBox.innerHTML+='<p>经度:'+pos.coords.longitude+'<br/>纬度:'+pos.coords.latitude
+'<br/>精确度:'+pos.coords.accuracy+'<br/>海拔:'+pos.coords.altitude
+'<br/>海拔准确度:'+pos.coords.altitudeAccuracy
+'<br/>时间:'+pos.timeStamp
+'</p>'
},function(err){
//定位失败后回调的函数,错误的结果以参数的形式传给该函数
alert(err.code);
},{
//设置的额外参数,可选参数
enableHighAccuracy:false,
maximumAge:0,
timeout:5000,
frequency:100, //每隔1s请求一次,在pc端效果不明显
});
}
}
stopGeo.onclick=function(){
//停止重复定位
clearWatch(wacthId);
}
</script>
watchPosition会主动进行重复定位,一般用于移动端
4. 百度地图
上面的geoLocation对象仅仅只是获取了用户当前的位置(经纬度),如果要让用户清晰形象的知道所处的位置,需要将当前的位置展示到地图上,因此需结合百度地图使用。
百度地图API:http://lbsyun.baidu.com/index.php?title=jspopular
百度地图的JavaScript APIv1.4及以前版本无须申请密钥(ak),自v1.5版本开始需要先申请密钥(ak)。
1) 引入方式
使用V1.4及以前版本的引用方式:
<script src="http://api.map.baidu.com/api?v=1.4" type="text/javascript"></script>
使用V2.0版本的引用方式:
<script src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥" type="text/javascript"></script>
2) 地图的简单使用
<body>
<divid="container"></div>
<!--<scripttype="text/javascript"src="http://api.map.baidu.com/api?v=2.0&ak=qOrCRdE01TFgS1YyGmraxRPfO8cYo0HV">
//v2.0版本的引用方式:src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥"
//v1.4版本及以前版本的引用方式:src="http://api.map.baidu.com/api?v=1.4"
</script>-->
<scripttype="text/javascript"src="http://api.map.baidu.com/api?v=1.3">
//v2.0版本的引用方式:src="http://api.map.baidu.com/api?v=2.0&ak=您的密钥"
//v1.4版本及以前版本的引用方式:src=http://api.map.baidu.com/api?v=1.4
//注意地图框架内部使用document.write往文档内添加内容,因此不可以使用异步加载(aysnc或defer)
</script>
<scripttype="text/javascript">
var map = newBMap.Map("container"); // 创建地图实例
varpoint = newBMap.Point(116.404,39.915); // 创建点坐标,第一个参数经度,第二个参数是纬度
map.centerAndZoom(point,15); //初始化地图,设置中心点坐标和地图级别
</script>
</body>
效果图:
3) 添加标注覆盖物:
添加覆盖物很简单,只需假设如下两句
var marker = newBMap.Marker(point); // 创建标注
map.addOverlay(marker); // 将标注添加到地图中
移除覆盖物
map.removeOverlay(marker);
设置覆盖的事件:覆盖物在页面上也是一个普通的元素,可以通过类似绑定事件的方式对其设置,大部分事件和原生js支持的事件名相同(如点击,拖拽等),当然也有部分不同的(如右击rightclick)
例子:在指定的点上添加覆盖物,并允许该覆盖物可以拖拽,拖拽结束时弹出停放的位置,当点击时覆盖物时弹出信息窗,鼠标右击时弹出菜单,可以点击删除项移除覆盖物
<!DOCTYPEhtml>
<html>
<head>
<metacharset="UTF-8">
<title></title>
<style>
html{height:100%}
body{height:100%;margin:0;padding:0;}
/*一定要设置高度,否则容器高度为0,显示不出地图*/
#container{height:100%;}
</style>
</head>
<body>
<!--必须指定容器id,用于显示地图-->
<divid="container"></div>
<divid="info"style="display:none;background: red;">这是我们的位置</div>
<!--引入地图框架-->
<!--<scripttype='text/javascript'src="http://api.map.baidu.com/api?v=1.3"></script>-->
<scripttype="text/javascript"src="http://api.map.baidu.com/api?v=2.0&ak=qOrCRdE01TFgS1YyGmraxRPfO8cYo0HV"></script>
<script>
varoInfo=document.getElementById("info");
//创建地图
var map=newBMap.Map('container');
//创建点
varpoint=newBMap.Point(116.404,39.915); //北京天安门坐标点
// var point=newBMap.Point(104.404, 35.915);
//初始化地图,设置中心点,并设置缩放级别
map.centerAndZoom(point,15);
//添加控件
map.addControl(newBMap.NavigationControl());//页面的方向及缩放控件,默认在左上角
map.addControl(newBMap.ScaleControl()); //页面中标尺控件,默认在左下角
map.addControl(newBMap.OverviewMapControl());//预览控件,似乎没有效果
map.addControl(newBMap.MapTypeControl());//地图类型切换切换控件,默认在右上角
// map.setCurrentCity("北京");
//添加标注
varmarker1=newBMap.Marker(point);
map.addOverlay(marker1);
//允许标注可拖拽
marker1.enableDragging();
//禁止拖拽:marker1.disableDragging();
//设置标注的点击事件
marker1.addEventListener('click',function(ev){
//alert('当前点击的位置:经度'+ev.point.lng+',纬度'+ev.point.lat);
//指定弹窗的宽度、高度以及标题等参数
varopts={width:200,height:100,title:'Web前端'};
oInfo.style.display=‘block’;//显示页面中在提示窗内的元素 //创建信息窗对象
//第一个参数:可以是页面html元素,也可以是字符串,表示弹窗显示的信息
//第二个参数:信息窗的设置参数
varinfoWind=newBMap.InfoWindow(oInfo,opts);
//或者
//var infoWind=new BMap.InfoWindow('这是我们现在的位置',opts);
//将信息窗显示到地图上
//第一个参数:待显示的信息窗对象
//第二个参数:指定信息窗显示的位置,为BMap.Point对象
// 常用的点有:ev.point(当前点击的位置点),map.getCenter()-->地图的中心点
map.openInfoWindow(infoWind,ev.point);
});
//监听标注的拖拽结束事件,拖拽结束时,弹出当前停放的位置
marker1.addEventListener('dragend',function(ev){
alert('当前标注(经度:'+ev.point.lng+',纬度:'+ev.point.lat+')');
});
//右击删除当前标注
/*marker1.addEventListener('rightclick',function(ev){
map.removeOverlay(ev.target);
});*/
//定义功能,删除覆盖物
functionremove(){
map.removeOverlay(marker1);
}
//定义右击菜单
varmenu=newBMap.ContextMenu();
//定义菜单项
//第一个参数:该菜单项的标题
//第二个参数:当用户点击该菜单项时回调的函数,这里回调删除覆盖物函数
//第三个参数:可选,该菜单的设置参数,可以指定菜单项的宽度及该项在页面中唯一的DOM id及该项的iconUrl
//注意:该对象时2.0 api才支持的
varitem=newBMap.MenuItem('删除',remove,{width:100,id:'removeItem',iconUrl:'icon.png'});
//将菜单项添加到右击菜单中
menu.addItem(item);
//将右击菜单添加到覆盖物上,这样当右击标注物时就显示上面定义好的菜单项
marker1.addContextMenu(menu);
//这些事件除了标注物具有外,整个地图map同样具有,如果针对整个地图设置事件,则对map对象采用同样的方式设置即可
</script>
</body>
</html>
可以将上面代码中的位置结合定位实现,使覆盖物标注在用户当前的位置