在學習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