很久沒寫文章了,以前一直有一個想法,就是作一個根據用戶行走的路線,獲取地理位置,而後把它們繪製出來,最後產生的效果,相似蝸牛行走留下的痕跡。html
最近思考了一下,搭了一個https,簡單實現了一下,提供一下思路給你們看看,具體的細節還有不少須要完善。html5
demo:
nginx
demo頁面地址: (不會泄露你的隱私,請用移動端訪問,耐心等待位置獲取)
https://www.yudonghan.com/snail/git
要作這樣一個東西首先要去了解html5提供了哪些地理信息接口,這些內容能夠在MDN上找到:
主要是一個 Geolocation.watchPosition() 和 Geolocation.getCurrentPosition()canvas
getCurrentPosition 是一次性的獲取你的地理信息位置,watchPosition是監聽地理信息位置的改變。瀏覽器
瞭解到接口之後,遇到的第一個問題是,發現普通的http協議因爲隱私限制,已經取消了對上述兩個接口的支持,解決方法是必須搭建https協議的服務器!
上網找到方法,我使用僞造的假證書搭建了nginx 的https服務,但問題是用戶在訪問的時候須要手動確認這個不安全的訪問,不過這也正常,做爲定位這樣敏感的信息,確實是須要極高的安全性。安全
我但願能夠過一段時間拿到一個定位,只有一個,因此我設置了一個時間週期的循環,並記錄當前在哪一個循環內,若是這個週期內已經拿到過watch接口獲得的位置,那麼我就不作操做,若是沒拿到過,我就給放到記錄裏,若是整個週期都沒拿到,也不要緊,我就拋棄這個週期,去獲取更精確的值。服務器
地理信息的返回,是帶有一個accurancy的精度值,是以米爲單位的,對地理信息的捨棄與否,主要取決於你指望的這個精確值。函數
關於繪製,這邊就是用一個最基本的帶有透明度的圓。在最開始,我會記錄下第一次進來的位置信息(對應畫布的粗略的中點),以後每次跟此次進行比對,算出差值,而後放大,映射到畫布座標,做爲圓心,繪製到畫布上。優化
直接看代碼:
(function () { // 初始化畫布 var canvas var ctx var width = 500; var height = 500; function initCanvas() { canvas = document.getElementById("snail_canvas"); canvas.width = width; canvas.height = height; ctx = canvas.getContext("2d"); } // 繪製點方法 function drawPoint(x, y, r) { ctx.fillStyle = "rgba(0, 0, 200, 0.1)"; ctx.beginPath(); ctx.arc(x, y, r, 0, 2 * Math.PI); ctx.fill(); } // 地理信息位置參數 var options = { enableHighAccuracy: true, desiredAccuracy: 20 } // 一些記錄用的變量 var pathArr = {} var pathIndex = 0 var watchID = navigator.geolocation.watchPosition(checkLocation, onError, options); var firstFlag = true var centerPos = {} var centerPoint = {} centerPoint.x = width / 2 centerPoint.y = height / 2 // 檢查位置,每次地理信息變化都會通過這個函數 function checkLocation(position) { // 精度小於指望值過濾 if (position.coords.accuracy <= options.desiredAccuracy) { // 當前週期內只能記錄一次地理座標 if (!pathArr[pathIndex]) { var offset pathArr[pathIndex] = position document.getElementById('container').innerHTML += 'render in period' + pathIndex + '<br>'; // 獲取地理座標 var geoX = position.coords.longitude var geoY = position.coords.latitude // 全局第一次座標做爲咱們畫布的中點繪製 if (firstFlag) { offset = { x: 0, y: 0 } centerPos = { x: geoX, y: geoY } firstFlag = false } else { // 後來的座標咱們算跟第一次座標的差值記錄 offset = { x: geoX - centerPos.x, y: geoY - centerPos.y } } // 將差值傳給點渲染方法 renderPoint(offset) } } } // 地理座標放大倍數 var mulTime = 100000 function renderPoint(offset) { // 用畫布中點疊加放大後的差值,並繪製該點 var x = centerPoint.x + offset.x * mulTime var y = centerPoint.y + offset.y * mulTime drawPoint(x, y, 5) document.getElementById('container').innerHTML += '**** : ' + offset.x + '+' + offset.y + '<br>'; } function main() { initCanvas() // 設置一個循環來計算週期,每一個週期最多獲取一次地理信息位置,最少0次 setInterval(function () { pathIndex ++ }, 2000) } // 頁面加載和從新進入頁面的時候都會運行main window.onload = main; window.focus = main; //失敗時 function onError(error){ switch(error.code){ case 1: alert("位置服務被拒絕"); break; case 2: alert("暫時獲取不到位置信息"); break; case 3: alert("獲取信息超時"); break; case 4: alert("未知錯誤"); break; } } })()
目前這套系統還存在不少問題,好比精度問題,常常產生繪製不許確的狀況。
繪製上,更是不夠細緻,尤爲是當你走出畫布是沒法記錄的,當前的放大值過大,還很容易走出畫布。該點後續能夠優化。
最大問題:做爲html5頁面,你必須一直開啓瀏覽器訪問才能持續獲取定位,不能黑屏,不能暫存瀏覽器,致使這個頁面很是不實用!
進化:目前是透明圓點的繪製方法,能夠改用折現等其餘方式。圓點能夠自定義顏色,大小,成爲真正的步行繪製系統。能夠自定義放大倍數,根據用戶的速度,改變不一樣的放大。