手记

原生javascript-手势解锁的制作

思路和效果

现在几乎每个app应用都会有手势解锁这一功能,微信支付宝等关键操作的时候都会转到手势解锁,想要在手势解锁这个功能上出彩的话,必须要自己来实现才能个性化的进行手势解锁。比如现在都是9个点画出的图形可能会简单,能被别人轻易试出密码,如果换成30个点那样画出的图形就会相当复杂了,可以增加手势密码的复杂度。另外自己可以指定其各种元素的颜色、线条的粗细等,都可以达到令人耳目一新的效果。本例是在移动端实现的

思路:

效果:

代码实现

<html>
<head>
    <style>
        * {
            margin: 0px;
            padding: 0px;
            user-select: none;
        }
        
        canvas {
            cursor: pointer;
            width: 300px;
            height: 300px;
        }
    </style>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
</head>
<body>
    <canvas id="canvas" width="600" height="600"></canvas>
</body>
<script>
    // 获取canvas对象
    var canvas = document.getElementById("canvas");
    // 手指是否按下
    var IStouchdown = false;
    // 设置画布宽度-是样式宽度的两倍,为了适应移动端的设备像素比
    canvas.width = window.innerWidth * 2
        // 设置画布高度
    canvas.height = window.innerWidth * 2
        // 设置画布的样式宽度
    canvas.style.width = window.innerWidth + "px";
    // 设置画布的样式高度
    canvas.style.height = window.innerWidth + "px";
    // 获取画布宽度
    var width = canvas.width;
    // 获取画布高度
    var height = canvas.height;
    // 获取画布上下文
    var cxt = canvas.getContext("2d");
    // 指定画布拐角的样式
    cxt.lineJoin = "round";
    // 画圆点 宽高都化为4份 确定圆点的间距
    // 定义点的数组
    var dotArr = [];
    // 定义横向的间距
    var dotSpaceX = Math.round(width / 4);
    // 定义纵向的间距
    var dotSpaceY = Math.round(height / 4);
    // 鼠标经过圆点时自动吸附的距离
    var adsorbSpace = width / 20;
    // 定义计数器,用于嵌套循环的计数
    var index = 1;
    for (var i = 1; i <= 3; i++) {
        for (var j = 1; j <= 3; j++) {
            index++
            dotArr.push({
                // 横坐标
                x: i * dotSpaceX,
                // 纵坐标
                y: j * dotSpaceY,
                // 是否已经被连线
                isLink: false,
                // 数字
                num: index
            });
        }
        index++
    }
    // 圆点的半径的大小
    var pieRadius = width / 12;
    // 定义路径的点的集合
    var path = [];
    drawPie();
    // 绘制9个圆形
    function drawPie() {
        for (var k = 0; k < dotArr.length; k++) {
            var item = dotArr[k];
            // 开始一条路径,或重置当前的路径
            cxt.beginPath();
            // 定义路径的样式
            cxt.strokeStyle = "gray";
            // 定义路径的宽度
            cxt.lineWidth = "2";
            // 画圆形
            cxt.arc(item.x, item.y, pieRadius, 0, Math.PI * 2, true);
            // 创建从当前点到开始点的路径
            cxt.closePath();
            // 在画布上绘制确切的路径
            cxt.stroke();
        }
    }
    // 监听画布上手指按下
    canvas.addEventListener("touchstart", function(e) {
            // 手指按下
            IStouchdown = true;
            // 开始一条路径,或重置当前的路径
            cxt.beginPath();
            draw(e)
        }, false)
        // 监听画布上手指移动
    canvas.addEventListener("touchmove", function(e) {
            draw(e)
            e.preventDefault();
        }, false)
        // 监听屏幕手指抬起-手指抬起的地方可能是画布之外
    document.addEventListener("touchend", function(e) {
            // 手指抬起
            IStouchdown = false;
            // 清空画布
            clear();
            // 重新绘制圆
            drawPie();
            // 定义密码字段
            var pass = ""
                // 绘制路径
            for (var k = 0; k < path.length; k++) {
                cxt.strokeStyle = "green";
                cxt.lineWidth = "3";
                cxt.lineTo(path[k].x, path[k].y);
                cxt.stroke();
                // 密码拼接字符串
                pass += path[k]["num"] + ""
            }
            // 绘制亮点
            for (var k = 0; k < path.length; k++) {
                cxt.beginPath();
                cxt.fillStyle = "green";
                cxt.strokeStyle = "green";
                cxt.arc(path[k].x, path[k].y, pieRadius / 4, 0, Math.PI * 2, true);
                cxt.closePath();
                cxt.fill();
                cxt.stroke();
            }
            // 判断密码是否正确
            if ("26101112" == pass) {
                setTimeout(function() {
                    alert("解锁成功")
                })
            } else {
                // 如果不正确,清空画布重新绘制九个圆
                clear();
                drawPie();
                setTimeout(function() {
                        alert("解锁失败")
                    })
                    // 初始化path数组和圆点的缓存数组
                path = [];
                for (var k = 0; k < dotArr.length; k++) {
                    var item = dotArr[k];
                    item.isLink = false;
                }
            }
        }, false)
        // 清空画布
    function clear() {
        cxt.clearRect(0, 0, width, height);
    }
    // 绘制路径
    function draw(e) {
        // 手指按下的情况
        if (IStouchdown) {
            // 获取手指在画布上按下的或移动的点--乘以2也是处理设备像素比
            var x = (e.touches[0]["clientX"] - e.target.offsetLeft) * 2;
            var y = (e.touches[0]["clientY"] - e.target.offsetTop) * 2;
            // 循环九个圆形
            for (var i = 0; i < dotArr.length; i++) {
                var item = dotArr[i];
                // 判断点与手指按下的点的距离是否在吸附距离之内
                if (Math.abs(item.x - x) < adsorbSpace && Math.abs(item.y - y) < adsorbSpace) {
                    // 如果圆点在没有被连接的情况
                    if (!dotArr[i]["isLink"]) {
                        // 圆点存入路径数组
                        path.push(item);
                        // isLink属性改为true
                        dotArr[i]["isLink"] = true;
                    }
                }
            }
            // 清空画布
            clear();
            // 重新绘制圆
            drawPie();
            // 根据路径中圆点 绘制绿色的圆 制造点亮的效果
            for (var k = 0; k < path.length; k++) {
                cxt.beginPath();
                cxt.fillStyle = "green";
                cxt.arc(path[k].x, path[k].y, pieRadius / 4, 0, Math.PI * 2, true);
                cxt.closePath();
                cxt.fill();
            }
            cxt.beginPath();
            // 根据圆心绘制手指经过的路径
            for (var k = 0; k < path.length; k++) {
                cxt.strokeStyle = "green";
                cxt.lineWidth = "3";
                cxt.lineTo(path[k].x, path[k].y);
                cxt.stroke();
            }
            cxt.strokeStyle = "green";
            cxt.lineWidth = "3";
            // 手指移动中的点
            cxt.lineTo(x, y);
            cxt.stroke();
        }
    }
</script>
</html>



1人推荐
随时随地看视频
慕课网APP