根據地理信息繪畫的html5 小遊戲 - 簡單實現

很久沒寫文章了,以前一直有一個想法,就是作一個根據用戶行走的路線,獲取地理位置,而後把它們繪製出來,最後產生的效果,相似蝸牛行走留下的痕跡。html

最近思考了一下,搭了一個https,簡單實現了一下,提供一下思路給你們看看,具體的細節還有不少須要完善。html5

demo:
圖片描述nginx

demo頁面地址: (不會泄露你的隱私,請用移動端訪問,耐心等待位置獲取)
https://www.yudonghan.com/snail/git

1.地理信息接口

要作這樣一個東西首先要去了解html5提供了哪些地理信息接口,這些內容能夠在MDN上找到:
主要是一個 Geolocation.watchPosition()Geolocation.getCurrentPosition()canvas

getCurrentPosition 是一次性的獲取你的地理信息位置,watchPosition是監聽地理信息位置的改變。瀏覽器

2.https

瞭解到接口之後,遇到的第一個問題是,發現普通的http協議因爲隱私限制,已經取消了對上述兩個接口的支持,解決方法是必須搭建https協議的服務器!
上網找到方法,我使用僞造的假證書搭建了nginx 的https服務,但問題是用戶在訪問的時候須要手動確認這個不安全的訪問,不過這也正常,做爲定位這樣敏感的信息,確實是須要極高的安全性。安全

3.實現思路

我但願能夠過一段時間拿到一個定位,只有一個,因此我設置了一個時間週期的循環,並記錄當前在哪一個循環內,若是這個週期內已經拿到過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;
        }
    }
    
})()

4.問題

目前這套系統還存在不少問題,好比精度問題,常常產生繪製不許確的狀況。

繪製上,更是不夠細緻,尤爲是當你走出畫布是沒法記錄的,當前的放大值過大,還很容易走出畫布。該點後續能夠優化。

最大問題:做爲html5頁面,你必須一直開啓瀏覽器訪問才能持續獲取定位,不能黑屏,不能暫存瀏覽器,致使這個頁面很是不實用!

進化:目前是透明圓點的繪製方法,能夠改用折現等其餘方式。圓點能夠自定義顏色,大小,成爲真正的步行繪製系統。能夠自定義放大倍數,根據用戶的速度,改變不一樣的放大。

相關文章
相關標籤/搜索