本文將簡述一下如何經過HTML5和百度地圖開放平臺提供的API來實現對瀏覽器的定位,同時記錄了遇到的問題和解決方案。實現效果爲顯示出用戶所在的省市,即: XXX省 XXX市。javascript
利用HTML5 提供的API獲取到用戶的經緯度信息,再將用戶的經緯度信息傳到百度地圖開放平臺,百度地圖開放平臺根據提供的座標信息返回當前的省市。php
兼容性:Internet Explorer 9+, Firefox, Chrome, Safari 和 Opera 都支持Geolocation(地理定位).html
依賴:不依賴於任何庫和框架html5
使用HTML5 Geolocation API的getCurrentPosition() 方法可以獲取用戶的經緯度信息。java
getCurrentPosition() 經常使用參數有兩個,一個是成功時執行,一個時錯誤處理。若是getCurrentPosition()運行成功,則向第一個參數中規定的函數返回一個coordinates對象,用於提供位置信息。nginx
coordinates對象屬性以下:git
屬性 | 描述 |
---|---|
coords.latitude | 十進制數的緯度 |
coords.longitude | 十進制數的經度 |
coords.accuracy | 位置精度 |
coords.altitude | 海拔,海平面以上以米計 |
coords.altitudeAccuracy | 位置的海拔精度 |
coords.heading | 方向,從正北開始以度計 |
coords.speed | 速度,以米/每秒計 |
timestamp | 響應的日期/時間 |
其中,latitude、longitude 以及 accuracy 屬性 是固定返回的屬性,其餘屬性在可用狀態下才會一塊兒返回。chrome
若是getCurrentPosition()運行失敗,則向第二個參數中規定的函數返回一個error對象,用於提供錯誤信息。api
屬性 | 描述 |
---|---|
code | 1: PERMISSION_DENIED,用戶不容許地理定位 2: POSITION_UNAVAILABLE,沒法獲取當前位置 3:TIMEOUT,操做超時 |
message | 返回相應的錯誤信息 |
下例是一個簡單的地理定位實例,可返回用戶位置的經度和緯度:瀏覽器
function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition, showError); } else { console.log("該瀏覽器不支持獲取地理位置。"); } } function showPosition(position) { console.log("緯度: " + position.coords.latitude + " 經度: " + position.coords.longitude); } function showError(error) { console.log(error); }
參考資料:
百度地圖API使用BMap做爲命名空間,全部類均在該命名空間之下,好比:BMap.Map、BMap.Control、BMap.Overlay。
首先,咱們須要引入百度地圖API文件:
<script src="http://api.map.baidu.com/api?v=1.4"></script> //參數v表示您加載API的版本,使用JavaScript APIv1.4及之前版本可以使用此方式引用。 <script src="http://api.map.baidu.com/api?v=2.0&ak=您的密鑰"></script> //使用JavaScript APIv2.0請先申請密鑰ak,按此方式引用。
而後,咱們再建立一個地理點座標:
var point = new BMap.Point(116.404, 39.915);
構造函數 | 描述 |
---|---|
Point(lng: Number, lat: Number) | 以指定的經度和緯度建立一個地理點座標 |
最後,咱們能夠經過建立好的點座標獲取到用戶的地址解析:
var myGeo = new BMap.Geocoder(); myGeo.getLocation(point, function (result) { console.log(result.addressComponents.province + ' ' + result.addressComponents.city); }
構造函數 | 描述 |
---|---|
Geocoder() | 建立一個地址解析器的實例 |
方法 | 返回值 | 描述 |
---|---|---|
getPoint(address: String, callback: Function, city: String) | none | 對指定的地址進行解析。若是地址定位成功,則以地址所在的座標點Point爲參數調用回調函數。不然,回調函數的參數爲null。city爲地址所在的城市名,例如「北京市」 |
getLocation(point: Point, callback: Function, options: LocationOptions) | none | 對指定的座標點進行反地址解析。若是解析成功,則回調函數的參數爲GeocoderResult對象,不然回調函數的參數爲null |
參考資料:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> </head> <body> <p id="test"></p> </body> <script src="https://api.map.baidu.com/api?v=2.0&ak=您的密鑰" type="text/javascript"></script> <script> function getLocation() { if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(showPosition, showError); } else { console.log("該瀏覽器不支持獲取地理位置。"); } } function showPosition(position) { var point = new BMap.Point(position.coords.longitude, position.coords.latitude); var myGeo = new BMap.Geocoder(); myGeo.getLocation(point, function (result) { alert(result.addressComponents.province + ' ' + result.addressComponents.city); }) } function showError(error) { console.log(error); } getLocation(); </script> </html>
按照上面的步驟去作,理論上是能夠實現咱們的功能。但事實並不是如此,不信你能夠起個服務驗證一下看看。
經過驗證,你會發如今Chrome 瀏覽器中使用http://localhost:8080
或者 http://127.0.0.1:8080
能夠正常獲取到瀏覽器的地理位置,但經過IP或者域名的形式,如:http://172.21.3.82:8080
和 http://b.cunzhang.com
進行訪問時卻獲取不到。
爲何呢?打開控制檯,你會發現有如下錯誤信息:
Only secure origins are allowed (see: https://goo.gl/Y0ZkNV).
「只有在安全來源的狀況才才被容許」。錯誤信息裏還包含了一個提示連接,咱們不妨打開這個連接(https://goo.gl/Y0ZkNV)看看。原來,爲了保障用戶的安全,Chrome瀏覽器認爲只有安全的來源才能開啓定位服務。那什麼樣纔算是安全的來源呢?在打開連接的頁面上有這麼一段話:
「Secure origins」 are origins that match at least one of the following (scheme, host, port) patterns:
- (https, *, *)
- (wss, *, *)
- (*, localhost, *)
- (*, 127/8, *)
- (*, ::1/128, *)
- (file, *, —)
- (chrome-extension, *, —)
This list may be incomplete, and may need to be changed. Please discuss!
大概意思是說只有包含上述列表中的scheme
、host
或者port
纔會被認爲是安全的來源,如今這個列表還不夠完整,後續可能還會有變更,有待討論。
這就能夠解釋了爲何在http://localhost:8080
和 http://127.0.0.1:8080
訪問下能夠獲取到瀏覽器的地理位置,而在http://172.21.3.82:8080
和 http://b.cunzhang.com
確獲取不到了。若是須要在域名訪問的基礎上實現地位位置的定位,那咱們只能把http
協議升級爲https
了。
從http
升級爲https
要先獲取一張證書。
證書是一個二進制文件,裏面包含通過認證的網站公鑰和一些元數據,要從經銷商購買。因爲我司已經升級到了https
,就不須要我瞎折騰了,感興趣的能夠參考阮一峯老師的這篇文章《HTTPS 升級指南》。雖然我司對外開放的網站都已經全面升級爲https
,可是內網的測試環境仍是沒有升級到https
,下面將簡述一下如何經過nginx
來搭建一個https
服務。
要設置安全服務器,使用公共鑰建立一對公私鑰對。大多數狀況下,發送證書請求(包括本身的公鑰),你的公司證實材料以及費用到一個證書頒發機構(CA)。CA驗證證書請求及您的身份,而後將證書返回給您的安全服務器。
可是內網實現一個服務器端和客戶端傳輸內容的加密,能夠本身給本身頒發證書,只須要忽略掉瀏覽器不信任的警報便可!
XXXX.key CA私鑰:
openssl genrsa -des3 -out XXXX.key 2048
XXXX.crt CA根證書(公鑰):
openssl req -new -x509 -days 365 -key XXXX.key -out XXXX.crt
在配置你的公鑰過程當中會讓你填寫一些信息,這時候隨便填一下就能夠了。
worker_processes 1; events { worker_connections 1024; } http { include mime.types; default_type application/octet-stream; sendfile on; keepalive_timeout 65; upstream sslfpm { server 127.0.0.1:9000 weight=10 max_fails=3 fail_timeout=20s; } server { listen 443; server_name b.cunzhang.com; #爲一個server開啓ssl支持 ssl on; #爲虛擬主機指定pem格式的證書文件 ssl_certificate /etc/ssl/cunzhang_test.crt; #爲虛擬主機指定私鑰文件 ssl_certificate_key /etc/ssl/cunzhang_test.key; #客戶端可以重複使用存儲在緩存中的會話參數時間 ssl_session_timeout 5m; #指定使用的ssl協議 ssl_protocols SSLv3 TLSv1; #指定許可的密碼描述 ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; #SSLv3和TLSv1協議的服務器密碼需求優先級高於客戶端密碼 ssl_prefer_server_ciphers on; location / { root /etc/ssl/; autoindex on; autoindex_exact_size off; autoindex_localtime on; } # redirect server error pages to the static page /50x.html # error_page 500 502 503 504 /50x.html; error_page 404 /404.html; location = /50x.html { root /usr/share/nginx/www; } location = /404.html { root /usr/share/nginx/www; } # proxy the PHP scripts to fpm location ~ \.php$ { access_log /etc/ssl/ssl.access.log ; error_log /etc/ssl/ssl.error.log; root /etc/ssl/; fastcgi_param HTTPS on; include /usr/local/etc/nginx/fastcgi_params; fastcgi_pass sslfpm; } } }
虛擬主機文件配置以後還有記得在hosts給你的域名配置好ip地址,這樣就能夠經過https
訪問到你的網頁實現定位功能了。
參考資料: