zoukankan      html  css  js  c++  java
  • 根据地理信息绘画的html5 小游戏

    好久没写文章了,之前一直有一个想法,就是做一个根据用户行走的路线,获取地理位置,然后把它们绘制出来,最后产生的效果,类似蜗牛行走留下的痕迹。

    最近思考了一下,搭了一个https,简单实现了一下,提供一下思路给大家看看,具体的细节还有很多需要完善。

    demo:
    图片描述

    demo页面地址: (不会泄露你的隐私,请用移动端访问,耐心等待位置获取)
    https://www.yudonghan.com/snail/

    1.地理信息接口

    要做这样一个东西首先要去了解html5提供了哪些地理信息接口,这些内容可以在MDN上找到:
    主要是一个 Geolocation.watchPosition()Geolocation.getCurrentPosition()

    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页面,你必须一直开启浏览器访问才能持续获取定位,不能黑屏,不能暂存浏览器,导致这个页面非常不实用!

    进化:
    目前是透明圆点的绘制方法,可以改用折现等其他方式。
    圆点可以自定义颜色,大小,成为真正的步行绘制系统。
    可以自定义放大倍数,根据用户的速度,改变不同的放大。

  • 相关阅读:
    APP的LOGO设计需求
    App 中使用 Iconfont 的整套方案
    UI流程总结
    sketch制作LOGO(一)---环形光晕
    Sketch插件--Rename It
    Sketch Measure使用教程
    04 流程控制
    03 python语法注释、用户交互、格式化输出、基本数据类型、运算符
    02编程语言及python初识
    第一课
  • 原文地址:https://www.cnblogs.com/10manongit/p/12903981.html
Copyright © 2011-2022 走看看