在学习navigator.geolocation的时候,有一个实例是获取坐标后显示在谷歌地图上。众所周知,谷歌地图国内并不能直接访问,得用特殊手段,那我要测试的时候还要开着梯子挺麻烦的,想给别人用也得那个人能访问谷歌地图先。
地图不止谷歌一家有嘛,咱国内还是可以用用百度地图、必应地图、高德地图这些。这篇文章记录如何在百度地图上显示使用navigator.geolocation返回的定位坐标。
首先我们要在百度地图开放平台上注册开发者,这样才能申请百度地图的秘钥,有了秘钥才能够使用百度地图的服务,这里就不吧过程写出来了。
我们需要在网页中使用百度地图,那我们就创建一个浏览器端的百度地图应用,选择自己想要的服务(因为我第一次接触这个,不知道哪些服务对应啥功能,就先全勾上了),白名单因为我是在本地测试的,网页不在服务器上运行,自然也没有域名,所以Referer白名单就设置成了*。
创建好后我们就可以在应用列表中看到我们刚刚创建的应用了:
这里的AK号非常重要,我们是要用这个AK号来链接百度地图的。
百度地图官方有提供实例和开发文档来帮助我们熟悉它家的产品,本篇文章涉及到内容的官方文档会放在下面的参考链接中。
因为我使用Chrome在本地运行包含使用navigator.geolocation定位的文件,它压根定位不了,Firefox却能正常定位,那就在Firefox上运行本次的实例吧。
我们来写个简单的页面。这个页面有两个<div>区域,一左一右,左边的用来显示一些获取到的坐标信息以及放操作按钮,右边就是显示百度地图啦。
1 <head> 2 <meta charset="UTF-8" /> 3 <title>定位显示在百度地图上</title> 4 <style> 5 body { 6 margin:0px; 7 padding:0px; 8 } 9 /* 显示详细信息的区域 */ 10 #detail { 11 width:30%; 12 height:750px; 13 background-color:#DDDDDD; 14 position:absolute; 15 left:0px; 16 top:0px; 17 padding-left:10px; 18 } 19 /* 百度地图区域的样式 */ 20 #baiduMap { 21 width:70%; 22 height:750px; 23 position:absolute; 24 right:0px; 25 top:0px; 26 } 27 </style> 28 </head> 29 30 <body> 31 <div id="detail"> 32 <p id="positionState">定位状态:停止</p> 33 <p id="positionInformation">定位信息:<br />经度:<br />纬度:</p> 34 <button onclick="getPos()">获取定位</button> 35 </div> 36 <div id="baiduMap"></div> 37 </body>
在<head>中引入百度地图API文件,标橙的部分就是我们上面创建应用的AK号了:
1 <head> 2 <script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=rj3D8rKFVj3QqNVKNYBFipdA3XMtfN4v"></script> 3 </head>
在<body>中的<script>中创建百度地图的实例(BMap.Map),传递的参数就是我们用来显示百度地图的区域,本例中使用一个id=baiduMap的<div>区域作为显示区域,所以传递的参数就是这个<div>区域的id:
1 //创建Map实例 2 var map = new BMap.Map("baiduMap");
之后我们初始化地图的位置,初始化地图的位置需要设置经纬度来设置地图中心定位的坐标(BMap.Point),这里设置成经度116.404,纬度39.915(天安门的坐标),设置地图缩放级别,值越大地图比例就越小。据官方API文档上的介绍,当地图的类型的BMAP_NORMAL_MAP时(可以使用setMapType()方法设置)时,需要在调用centerAndZoom之前要用setCurrentCity()来设置你设置坐标的城市,这里我们就设置成北京:
1 //设置地图显示的城市 2 map.setCurrentCity("北京"); 3 //设置地图中心点的坐标 4 var centerPoint = new BMap.Point(116.404,39.915); 5 //初始化地图,设置缩放级别为15 6 map.centerAndZoom(centerPoint,15);
这个时候我们就能够看到地图了:
但是这个地图此时并不能放大缩小,放大缩小功能呢是需要我们设置开启的,默认是不启动的。
我们通过Bmap.enableScrollWheelZoom()函数可以开启和关闭地图的放大缩小功能,传递true开启放大缩小功能,传递false关闭放大缩小功能:
1 //开启鼠标滚轮缩放 2 map.enableScrollWheelZoom(true);
这个时候就可以放大缩小了:
在地图API示例中,有在右上角添加了一个控件:切换地图显示模式,可以选择地图模式和混合模式(实景+地图坐标)。
创建BMap.MapTypeControl对象,设置能切换的类型有哪些(BMAP_NORMAL_MAPH地图模式 和 BMAP_HYBRID_MAP混合模式),然后使用addControl来添加这个控件:
1 //创建切换地图显示类型的控件 2 var mapTypeCon = new BMap.MapTypeControl({ 3 mapTypes:[ 4 BMAP_NORMAL_MAP, 5 BMAP_HYBRID_MAP 6 ] 7 }); 8 //添加切换地图显示类型的控件 9 map.addControl(mapTypeCon);
效果如下:
这个时候,百度地图导入的部分就暂时告一段落落了,接下来就是结合navigator.geolocation将获取到的定位信息显示在地图上了。
我希望当我点击旁边的“获取定位”按钮,百度地图就会定位获取到的定位位置,并且显示一个标记。
我们先获取展示信息的两个元素
1 //获取显示定位状态的元素 2 var posState = document.getElementById("positionState"); 3 //获取显示定位信息的元素 4 var posInformation = document.getElementById("positionInformation");
然后写三个函数,一个是点击按钮获取一次定位的事件,一个是定位成功时回调的函数,一个是定位失败时回调的函数。
获取一次定位的事件我们绑定在上面的上面的<button>的onclick事件上,因为偷懒所以我在网页结构的时候就给<button>绑上啦(你个懒鬼)
1 //点击按钮获取定位 2 function getPos() { 3 //判断用户是否支持定位 4 if(navigator.geolocation) { 5 //支持则获取定位,获取成功回调showPosition,失败回调showError 6 navigator.geolocation.getCurrentPosition(showPosition,showError); 7 } 8 else { 9 //不支持则修改提示信息告知用户 10 posInformation.innerHTML = "您的浏览器不支持定位"; 11 } 12 }
定位失败时执行的回调函数showError中,我们获取错误代码,然后用个switch来获取并修改提示信息,代码对应的错误信息可以看MDN中PositionError的条目,或者发生错误时调用PositionError.message查看:
1 //获取定位信息失败时执行的函数 2 function showError(error) { 3 //在控制台直接打印错误代码和错误信息 4 console.log("错误代码:"+error.code + "\n错误信息:" + error.message); 5 6 //使用switch对error的错误代码进行判断,然后修改提示信息 7 switch(error.code){ 8 //用户拒绝请求 9 case error.PERMISSION_DENIED: 10 posInformation.innerHTML = "用户拒绝获取地理位置的请求"; 11 break; 12 //位置信息不可用 13 case error.POSITION_UNAVAILABLE: 14 posInformation.innerHTML = "位置信息不可用"; 15 break; 16 //请求超时 17 case error.TIMEOUT: 18 posInformation.innerHTML = "请求用户地理位置超时"; 19 break; 20 //未知错误 21 case error.UNKNOWN_ERROR: 22 posInformation.innerHTML = "未知错误"; 23 break; 24 } 25 }
定位成功时回调的函数showPosition中,我们吧经纬度信息写在左侧,并且在百度地图上定位我们输入的坐标,并在上面添加一个遮蔽物(在百度地图上出现的定位点啊、路线图啊被称作遮蔽物)标明它定位到的位置。
1 //成功获取定位 2 function showPosition(Position) { 3 //修改左侧坐标信息 4 posInformation.innerHTML = "定位信息:<br />经度:" + Position.coords.longitude + 5 "<br />纬度:" + Position.coords.latitude; 6 //创建一个变量储存坐标 7 var myPos = new BMap.Point(Position.coords.longitude,Position.coords.latitude); 8 //在百度地图上定位 9 map.centerAndZoom(myPos,15); 10 //创建遮蔽物 11 var marker = new BMap.Marker(myPos); 12 //将遮蔽物绘制到地图上 13 map.addOverlay(marker); 14 }
这个时候我们就可以点击按钮获取定位。。。
啦?不对啊,这定位不是我获取定位的地方啊!怎么偏了呢???
其实,在百度地图开放平台的开发文档中,有这样一个条目,它是这么说的:
原来如此龙一,不是GPS采集真实的经纬度啊!
官方在地图API示例中有将GPS坐标转换成百度坐标的的实例,里面有详细的实例。先将坐标储存到数组中,然后创建一个BMap.Convertor对象,使用Convertor对象中的translate()方法进行转换。translate方法需要回调一个函数,我们再在这个函数中将获取到的坐标定位在百度地图中,这个时候的showPosition()函数应该是这样的:
1 //成功获取定位 2 function showPosition(Position) { 3 //创建一个变量储存坐标 4 var myPos = new BMap.Point(Position.coords.longitude,Position.coords.latitude); 5 //创建一个数组,用于储存坐标 6 var pointArr = []; 7 //将坐标放入数组中 8 pointArr.push(myPos); 9 10 //创建convertor对象,用于将坐标转换成百度地图的坐标 11 var convertor = new BMap.Convertor(); 12 //进行坐标转换,转换完成后回调函数translateCallback,可以传递第四个参数来延迟执行 13 convertor.translate(pointArr,1,5,translateCallback); 14 }
convertor.translate的语法在官方的JavaScript v3.0类参考中看到,善用页面内搜索功能(F3或者Ctrl+F),然后它就会告诉你参数2和参数3的具体含义在Web服务API中(心情复杂.jpg):
在坐标转化的回调函数中,我们获取转换后的坐标,然后在地图上定位以及创建遮蔽物,修改网页中的提示信息:
1 //坐标转换后回调的函数 2 function translateCallback(data) { 3 //data.status记录本次访问api状态,返回0为成功,失败则为返回其它数字 4 if(data.status === 0) { 5 //在百度地图上定位获取到的坐标 6 map.centerAndZoom(data.points[0],20); 7 //创建覆盖物 8 var marker = new BMap.Marker(data.points[0]); 9 //在地图上绘制覆盖物 10 map.addOverlay(marker); 11 //修改左侧坐标信息 12 posInformation.innerHTML = "定位信息:<br />经度:" + data.points[0].lng + 13 "<br />纬度:" + data.points[0].lat; 14 } 15 }
这个时候定位就比较精准啦:
基本上我们想要实现的效果就搞完啦,功能并不是很完善,比如我点两次获取定位它会标记两个点,不会删掉上一个点,这个部分就不放出来了(懒)。
可能删删改改有些朋友做到后面会有点懵逼,我就放出完整的内容在这里啦:
1 <!DOCTYPE html> 2 <html> 3 4 <head> 5 <meta charset="UTF-8" /> 6 <title>定位显示在百度地图上</title> 7 <script type="text/javascript" src="http://api.map.baidu.com/api?v=3.0&ak=rj3D8rKFVj3QqNVKNYBFipdA3XMtfN4v"></script> 8 <style> 9 body { 10 margin:0px; 11 padding:0px; 12 } 13 /* 显示详细信息的区域 */ 14 #detail { 15 width:30%; 16 height:750px; 17 background-color:#DDDDDD; 18 position:absolute; 19 left:0px; 20 top:0px; 21 padding-left:10px; 22 } 23 /* 百度地图区域的样式 */ 24 #baiduMap { 25 width:70%; 26 height:750px; 27 position:absolute; 28 right:0px; 29 top:0px; 30 } 31 </style> 32 </head> 33 34 <body> 35 <div id="detail"> 36 <p id="positionState">定位状态:停止</p> 37 <p id="positionInformation">定位信息:<br />经度:<br />纬度:</p> 38 <button onclick="getPos()">获取定位</button> 39 </div> 40 <div id="baiduMap"></div> 41 <script type="text/javascript"> 42 //创建Map实例 43 var map = new BMap.Map("baiduMap"); 44 //设置地图显示的城市 45 map.setCurrentCity("北京"); 46 //设置地图中心点的坐标 47 var centerPoint = new BMap.Point(116.404,39.915); 48 //初始化地图,设置缩放级别为15 49 map.centerAndZoom(centerPoint,15); 50 //开启鼠标滚轮缩放 51 map.enableScrollWheelZoom(true); 52 //创建切换地图显示类型的控件 53 var mapTypeCon = new BMap.MapTypeControl({ 54 mapTypes:[ 55 BMAP_NORMAL_MAP, 56 BMAP_HYBRID_MAP 57 ] 58 }); 59 //添加切换地图显示类型的控件 60 map.addControl(mapTypeCon); 61 62 //获取显示定位状态的元素 63 var posState = document.getElementById("positionState"); 64 //获取显示定位信息的元素 65 var posInformation = document.getElementById("positionInformation"); 66 67 68 //点击按钮获取定位 69 function getPos() { 70 //判断用户是否支持定位 71 if(navigator.geolocation) { 72 //支持则获取定位,获取成功回调showPosition,失败回调showError 73 navigator.geolocation.getCurrentPosition(showPosition,showError); 74 } 75 else { 76 //不支持则修改提示信息告知用户 77 posInformation.innerHTML = "您的浏览器不支持定位"; 78 } 79 } 80 81 //成功获取定位 82 function showPosition(Position) { 83 //创建一个变量储存坐标 84 var myPos = new BMap.Point(Position.coords.longitude,Position.coords.latitude); 85 //创建一个数组,用于储存坐标 86 var pointArr = []; 87 //将坐标放入数组中 88 pointArr.push(myPos); 89 90 //创建convertor对象,用于将坐标转换成百度地图的坐标 91 var convertor = new BMap.Convertor(); 92 //进行坐标转换,转换完成后回调函数translateCallback,可以传递第四个参数来延迟执行 93 convertor.translate(pointArr,1,5,translateCallback); 94 } 95 96 //获取定位信息失败时执行的函数 97 function showError(error) { 98 //在控制台直接打印错误代码和错误信息 99 console.log("错误代码:"+error.code + "\n错误信息:" + error.message); 100 101 //使用switch对error的错误代码进行判断,然后修改提示信息 102 switch(error.code){ 103 //用户拒绝请求 104 case error.PERMISSION_DENIED: 105 posInformation.innerHTML = "用户拒绝获取地理位置的请求"; 106 break; 107 //位置信息不可用 108 case error.POSITION_UNAVAILABLE: 109 posInformation.innerHTML = "位置信息不可用"; 110 break; 111 //请求超时 112 case error.TIMEOUT: 113 posInformation.innerHTML = "请求用户地理位置超时"; 114 break; 115 //未知错误 116 case error.UNKNOWN_ERROR: 117 posInformation.innerHTML = "未知错误"; 118 break; 119 } 120 } 121 122 //坐标转换后回调的函数 123 function translateCallback(data) { 124 //data.status记录本次访问api状态,返回0为成功,失败则为返回其它数字 125 if(data.status === 0) { 126 //在百度地图上定位获取到的坐标 127 map.centerAndZoom(data.points[0],20); 128 //创建覆盖物 129 var marker = new BMap.Marker(data.points[0]); 130 //在地图上绘制覆盖物 131 map.addOverlay(marker); 132 //修改左侧坐标信息 133 posInformation.innerHTML = "定位信息:<br />经度:" + data.points[0].lng + 134 "<br />纬度:" + data.points[0].lat; 135 } 136 } 137 </script> 138 </body> 139 140 </html>
参考资料:
MDN - 使用地理位置定位:https://developer.mozilla.org/zh-CN/docs/Web/API/Geolocation/Using_geolocation
百度地图开放平台 - JavaScript API v3.0类参考:http://lbsyun.baidu.com/cms/jsapi/reference/jsapi_reference_3_0.html
百度地图开放平台 - 地图API演示 - 地图展示:http://lbsyun.baidu.com/jsdemo.htm#a1_2
MDN - PositionError:https://developer.mozilla.org/zh-CN/docs/Web/API/PositionError
MDN - PositionError.message:https://developer.mozilla.org/zh-TW/docs/Web/API/PositionError/message
百度地图开放平台 - 开发文档 - JavaScript API v2.0 - 坐标转换声明:http://lbsyun.baidu.com/index.php?title=jspopular/guide/coorinfo
百度地图开放平台 - 地图API演示 - 原始坐标转成百度坐标:http://lbsyun.baidu.com/jsdemo.htm#a5_2
百度地图开放平台 - Web服务API - 坐标转换:http://lbsyun.baidu.com/index.php?title=webapi/guide/changeposition