首页 > 技术文章 > navigator.geolocation的应用 - 将定位信息显示在百度地图上

cwsb 2019-05-15 10:06 原文

  在学习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

推荐阅读