【伯樂線上提示】:① 5月6日,谷歌開發者中心推出了一個 Web 開發最佳實踐手冊。伯樂線上資源頻道摘編該資源後,已邀請一些關注 Web 開發的朋友參與翻譯手冊。② 由於譯者朋友幾乎都是已在職,都是在工作之餘參與,每位的翻譯進度會不一樣(請理解),所以手冊中文版不會按照英文版章節順序釋出。③ 手冊中文版尚不完整,請不要轉載,謝謝合作。
【導讀】:地理位置(Geolocation)API 能讓你在使用者允許情況下獲取其位置資訊。這個功能可以作為使用者請求的一部分,比如導航使用者到指定位置;也可以為使用者生成的內容打上“位置標籤”,比如標記照片的拍照位置。
本章內容有
- 地理位置的用處
- 檢查相容性
- 檢測使用者當前位置
- 為網站測試地理位置功能
- 注意處理錯誤
- 減少啟動地理定位的硬體需要
- 設定超時以避免使用者等待過長
- 粗定位比精確定位好
長話短說
- 使用 API 前先檢測相容性
- 粗定位比精確定位好
- 注意處理錯誤
- 控制獲取資料的頻率以節省使用者電量
這個 API 是裝置無關的,它不管瀏覽器如何檢測位置,只要使用者能以標準方式請求和接收位置資訊即可。底層可能是通過 GPS、wifi 甚至是讓使用者手動輸入地址。這些查詢都需要花費一定時間,所以這個 API 是非同步的,在請求的時候要傳回撥函式。
地理位置的用處
- 為實際物理站點附近的使用者提供私人定製的使用者體驗。
- 根據使用者位置提供定製資訊(比如新聞)。
- 在地圖上顯示使用者位置。
- 在標籤資料中嵌入使用者的位置(比如照片的位置資訊)。
檢查相容性
如今大多數瀏覽器都支援地理位置 API,但在使用前最好還是檢查一下支援。
可以檢測 geolocation 物件的存在來測試相容性。
1 2 3 4 5 6 7 |
// check for Geolocation support if (navigator.geolocation) { console.log('Geolocation is supported!'); } else { console.log('Geolocation is not supported for this Browser/OS version yet.'); } |
檢測使用者當前位置
地理位置 API 提供了唯一的 getCurrentPosition() 函式來獲取使用者位置。呼叫此函式後會非同步反饋使用者當前的位置。
1 2 3 4 5 6 7 8 9 |
window.onload = function() { var startPos; var geoSuccess = function(position) { startPos = position; document.getElementById('startLat').innerHTML = startPos.coords.latitude; document.getElementById('startLon').innerHTML = startPos.coords.longitude; }; navigator.geolocation.getCurrentPosition(geoSuccess); }; |
如果這是該域名下的應用第一次請求許可權,瀏覽器一般會要求使用者的允許。在一些瀏覽器上還可能會有“允許”或“不允許”的偏好配置,這時瀏覽器就會直接繞過使用者確定。
根據瀏覽器使用的定位裝置,位置物件還可能會包含經緯度以外的資訊,比如海拔和方向。只有在定位系統返回資料的時候才能知道其包含的額外資訊。
為網站測試地理位置功能
對於使用 HTML5 地理位置支援的應用,可以利用不同的經緯度數值進行除錯。
Chrome 開發者工具支援重寫 navigator.geolocation 位置數值以及模擬重寫選單不支援的地理位置。
- 開啟開發者工具額重寫選單
- 選擇“重寫地理位置”(Override Geolocation),然後輸入 Lat = 41.4949819(緯度)和 Lon = -0.1461206(經度)
- 重新整理頁面應用重寫的地理位置
注意處理錯誤
查詢位置不一定成功;可能是 GPS 無法定位或者使用者突然中止了位置查詢。錯誤事件會呼叫 getCurrentPosition() 的第二個可選的引數,所以你可以在回撥函式裡告知使用者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
window.onload = function() { var startPos; var geoSuccess = function(position) { startPos = position; document.getElementById('startLat').innerHTML = startPos.coords.latitude; document.getElementById('startLon').innerHTML = startPos.coords.longitude; }; var geoError = function(position) { console.log('Error occurred. Error code: ' + error.code); // error.code 可以是: // 0: 未知錯誤 // 1: 許可權不足 // 2: 位置錯誤(位置供應商出錯) // 3: 超時 }; navigator.geolocation.getCurrentPosition(geoSuccess, geoError); }; |
減少啟動地理定位的硬體需要
許多情況下我們不需要使用者最新的位置,只需一個粗略的估值。
利用 maximumAge 可選屬性可以告知瀏覽器使用最近一次獲取的位置結果。這不僅在使用者已經請求過資料的情況下響應更快,而且不必啟動地理位置硬體介面比如 Wifi 三角定位或 GPS。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
window.onload = function() { var startPos; var geoOptions = { maximumAge: 5 * 60 * 1000, } var geoSuccess = function(position) { startPos = position; document.getElementById('startLat').innerHTML = startPos.coords.latitude; document.getElementById('startLon').innerHTML = startPos.coords.longitude; }; var geoError = function(position) { console.log('Error occurred. Error code: ' + error.code); // error.code 可以是: // 0: 未知錯誤 // 1: 許可權不足 // 2: 位置錯誤(位置供應商出錯) // 3: 超時 }; navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions); }; |
設定超時以避免使用者等待過長
沒有設定超時的話,位置請求有可能永遠都不返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
window.onload = function() { var startPos; var geoOptions = { timeout: 10 * 1000 } var geoSuccess = function(position) { startPos = position; document.getElementById('startLat').innerHTML = startPos.coords.latitude; document.getElementById('startLon').innerHTML = startPos.coords.longitude; }; var geoError = function(error) { console.log('Error occurred. Error code: ' + error.code); // error.code 可以是: // 0: 未知錯誤 // 1: 許可權不足 // 2: 位置錯誤(位置供應商出錯) // 3: 超時 }; navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions); }; |
粗定位比精確定位好
如果你只是需要知道離使用者最近的儲存點,則沒必要獲取1米的精度。設定這個 API 是為了儘快獲取粗定位。
如果你需要請求高精度,可以重寫 enableHighAccuracy 的預設設定。請謹慎使用:它會減慢解析速度並消耗更多電量。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
window.onload = function() { var startPos; var geoOptions = { enableHighAccuracy: true } var geoSuccess = function(position) { startPos = position; document.getElementById('startLat').innerHTML = startPos.coords.latitude; document.getElementById('startLon').innerHTML = startPos.coords.longitude; }; var geoError = function(error) { console.log('Error occurred. Error code: ' + error.code); // error.code 可以是: // 0: 未知錯誤 // 1: 許可權不足 // 2: 位置錯誤(位置供應商出錯) // 3: 超時 }; navigator.geolocation.getCurrentPosition(geoSuccess, geoError, geoOptions); }; |