使用HTML5地理位置定位到城市的方法及注意事項

介紹

本文將簡述一下如何經過HTML5和百度地圖開放平臺提供的API來實現對瀏覽器的定位,同時記錄了遇到的問題和解決方案。實現效果爲顯示出用戶所在的省市,即: XXX省 XXX市。javascript

實現思路

利用HTML5 提供的API獲取到用戶的經緯度信息,再將用戶的經緯度信息傳到百度地圖開放平臺,百度地圖開放平臺根據提供的座標信息返回當前的省市。php

兼容性及依賴

兼容性:Internet Explorer 9+, Firefox, Chrome, Safari 和 Opera 都支持Geolocation(地理定位).html

依賴:不依賴於任何庫和框架html5

HTML5 API

使用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

命名空間

百度地圖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

參考資料:

  1. 百度地圖 JavaScript API

  2. 百度地圖 JavaScript API起步

  3. 百度地圖 JavaScript API類參考

完整代碼示例

<!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:8080http://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!

大概意思是說只有包含上述列表中的schemehost或者port纔會被認爲是安全的來源,如今這個列表還不夠完整,後續可能還會有變更,有待討論。

這就能夠解釋了爲何在http://localhost:8080http://127.0.0.1:8080訪問下能夠獲取到瀏覽器的地理位置,而在http://172.21.3.82:8080http://b.cunzhang.com 確獲取不到了。若是須要在域名訪問的基礎上實現地位位置的定位,那咱們只能把http協議升級爲https了。

nginx搭建https服務

http升級爲https要先獲取一張證書。
證書是一個二進制文件,裏面包含通過認證的網站公鑰和一些元數據,要從經銷商購買。因爲我司已經升級到了https,就不須要我瞎折騰了,感興趣的能夠參考阮一峯老師的這篇文章《HTTPS 升級指南》。雖然我司對外開放的網站都已經全面升級爲https,可是內網的測試環境仍是沒有升級到https,下面將簡述一下如何經過nginx 來搭建一個https服務。

SSL 證書

要設置安全服務器,使用公共鑰建立一對公私鑰對。大多數狀況下,發送證書請求(包括本身的公鑰),你的公司證實材料以及費用到一個證書頒發機構(CA)。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訪問到你的網頁實現定位功能了。

參考資料:

Nginx搭建https服務器

相關文章
相關標籤/搜索