欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

canvas手势解锁源码

程序员文章站 2022-08-08 18:49:30
先放图 demo.html

先放图

canvas手势解锁源码

canvas手势解锁源码

demo.html

<!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
    <title>手势解锁</title>
    <style type="text/css">
        body{
            text-align: center;
            background: #305066;
        }
        h4{
            color: #22c3aa;
        }
    </style>
</head>
<body>
    <script type="text/javascript" src="src/index.js"></script>
    <script type="text/javascript">
        // 1、生成背景
        // 2、title生成
        // 3、用js动态生成canvas标签
        // 4、js方式动态生成h4标签和canvas标签
        new canvaslock({choosetype:3}).init();
    </script>
</body>
</html>

index.js

(function(){
        /**
         * 实现画圆和划线:
         * 1、添加事件touchstart、touchmove、touchend
         * 2、touchstart判断是否点击的位置处于圆内getposition,处于则初始化
         * lastpoint、restpoint
         * 3、touchmove做的就是:画圆drawpoint和画线drawline
         *
         * 实现自动画圆的效果
         * 1、检测手势移动的位置是否处于圆内
         * 2、圆内的话则画圆 drawpoint
         * 3、已经画过实心圆的圆,无需重复检测
         *
         * 实现解锁成功:
         * 1、检测路径是否是对的
         * 2、如果是对的就重置,圆圈变绿
         * 3、不对也重置,圆圈变红
         * 4、重置
         */

        window.canvaslock = function(obj){
            this.height = obj.height;
            this.width = obj.width;
            this.choosetype = obj.choosetype;
        };

        // js方式动态生成dom
        canvaslock.prototype.initdom = function(){
            var wrap = document.createelement('div');
            var str = '<h4 id="title" class="title">绘制解锁图案</h4>';
            wrap.setattribute('style','position: absolute;top:0;left:0;right:0;bottom:0;');


            var canvas = document.createelement('canvas');
            canvas.setattribute('id','canvas');
            canvas.style.csstext = 'background-color: #305066;display: inline-block;margin-top: 15px;';

            wrap.innerhtml = str;
            wrap.appendchild(canvas);

            var width = this.width || 300;
            var height = this.height || 300;
            
            document.body.appendchild(wrap);

            // 高清屏锁放
            canvas.style.width = width + "px";
            canvas.style.height = height + "px";

            canvas.width = width;
            canvas.height = height;

        }
        canvaslock.prototype.drawcle = function(x, y) { // 初始化解锁密码面板
            this.ctx.strokestyle = '#cfe6ff';
            this.ctx.linewidth = 2;
            this.ctx.beginpath();
            this.ctx.arc(x, y, this.r, 0, math.pi * 2, true);
            this.ctx.closepath();
            this.ctx.stroke();
        }
        canvaslock.prototype.createcircle = function() {// 创建解锁点的坐标,根据canvas的大小来平均分配半径

            var n = this.choosetype;
            var count = 0;
            this.r = this.ctx.canvas.width / (2 + 4 * n);// 公式计算
            this.lastpoint = [];
            this.arr = [];
            this.restpoint = [];
            var r = this.r;
            for (var i = 0 ; i < n ; i++) {
                for (var j = 0 ; j < n ; j++) {
                    count++;
                    var obj = {
                        x: j * 4 * r + 3 * r,
                        y: i * 4 * r + 3 * r,
                        index: count
                    };
                    this.arr.push(obj);
                    this.restpoint.push(obj);
                }
            }

            this.ctx.clearrect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);
            for (var i = 0 ; i < this.arr.length ; i++) {
                // 画圆函数
                this.drawcle(this.arr[i].x, this.arr[i].y);
            }
            //return arr;
        }

        // 程序初始化
        canvaslock.prototype.init = function() {
            this.initdom();
            this.canvas = document.getelementbyid('canvas');
            this.ctx = this.canvas.getcontext('2d');
            this.touchflag = false;
            // 1、确定半径
            // 2、确定每一个圆的中心坐标点
            // 3、一行3个圆14个半径,一行4个圆有18个半径
            this.createcircle();
            this.bindevent();
        }

        canvaslock.prototype.bindevent = function(){
            var self = this;
            this.canvas.addeventlistener("touchstart", function (e) {
                // 2、touchstart判断是否点击的位置处于圆内getposition,处于则初始化
                //          * lastpoint、restpoint
                
                // po有x和y,并且是相较于canvas边距
                var po = self.getposition(e);
                console.log(po.x)
                // 判断是否在圆内的原理:多出来的这条 x/y < r 在圆内
                for (var i = 0 ; i < self.arr.length ; i++) {
                    if (math.abs(po.x - self.arr[i].x) < self.r && math.abs(po.y - self.arr[i].y) < self.r) {
                         
                        self.touchflag = true;

                        // lastpoint存放的就是选中的圆圈的x/y坐标值
                        self.lastpoint.push(self.arr[i]);

                        self.restpoint.splice(i,1);
                        break;
                    }
                }


            }, false);

            this.canvas.addeventlistener("touchmove", function (e) {

               // touchmove做的就是:画圆drawpoint和划线drawline
               if (self.touchflag) {
                  self.update(self.getposition(e));
               }
            }, false);

            this.canvas.addeventlistener("touchend", function(e){
                if (self.touchflag) {
                    self.storepass(self.lastpoint);
                    settimeout(function(){
                       self.reset();
                   }, 300);
                }
            }, false);
        }

        canvaslock.prototype.getposition = function(e) {// 获取touch点相对于canvas的坐标
            var rect = e.currenttarget.getboundingclientrect();
            var po = {
                x: (e.touches[0].clientx - rect.left),
                y: (e.touches[0].clienty - rect.top)
            };
            return po;
        }

        
        canvaslock.prototype.update = function(po) {// 核心变换方法在touchmove时候调用
            this.ctx.clearrect(0, 0, this.ctx.canvas.width, this.ctx.canvas.height);

            // 重新画9个圆圈
            for (var i = 0 ; i < this.arr.length ; i++) { // 每帧先把面板画出来
                this.drawcle(this.arr[i].x, this.arr[i].y);
            }

            this.drawpoint();// 画圆
            this.drawline(po);// 画线

            // 1、检测手势移动的位置是否处于下一个圆内
            // 2、圆内的话则画圆 drawpoint
            // 3、已经画过实心圆的圆,无需重复检测
            for (var i = 0 ; i < this.restpoint.length ; i++) {
                if (math.abs(po.x - this.restpoint[i].x) < this.r && math.abs(po.y - this.restpoint[i].y) < this.r) {
                    this.drawpoint();
                    this.lastpoint.push(this.restpoint[i]);
                    this.restpoint.splice(i, 1);
                    break;
                }
            }

            console.log(this.lastpoint)

        }
        canvaslock.prototype.drawline = function(po) {// 解锁轨迹
            this.ctx.beginpath();
            this.ctx.linewidth = 3;
            this.ctx.moveto(this.lastpoint[0].x, this.lastpoint[0].y);
            for (var i = 1 ; i < this.lastpoint.length ; i++) {
                this.ctx.lineto(this.lastpoint[i].x, this.lastpoint[i].y);
            }
            this.ctx.lineto(po.x, po.y);
            this.ctx.stroke();
            this.ctx.closepath();
        }
        canvaslock.prototype.drawpoint = function() { // 初始化圆心 
            for (var i = 0 ; i < this.lastpoint.length ; i++) {
                this.ctx.fillstyle = '#cfe6ff';
                this.ctx.beginpath();
                this.ctx.arc(this.lastpoint[i].x, this.lastpoint[i].y, this.r / 2, 0, math.pi * 2, true);
                this.ctx.closepath();
                this.ctx.fill();
            }
        }

        // 1、检测路径是否是对的
        // 2、如果是对的就重置,圆圈变绿
        // 3、不对也重置,圆圈变红
        // 4、重置
        canvaslock.prototype.storepass = function() {
            if (this.checkpass()) {
                document.getelementbyid('title').innerhtml = '解锁成功';
                this.drawstatuspoint('#2cff26');
            }else{
                document.getelementbyid('title').innerhtml = '解锁失败';
                this.drawstatuspoint('red');
            }
        }
        canvaslock.prototype.checkpass = function() {
            var p1 = '123',
            p2 = '';
            for (var i = 0 ; i < this.lastpoint.length ; i++) {
                p2 += this.lastpoint[i].index;
            }
            return p1 === p2;
        }
        canvaslock.prototype.drawstatuspoint = function(type) {
            for (var i = 0 ; i < this.lastpoint.length ; i++) {
                this.ctx.strokestyle = type;
                this.ctx.beginpath();
                this.ctx.arc(this.lastpoint[i].x, this.lastpoint[i].y, this.r, 0, math.pi * 2, true);
                this.ctx.closepath();
                this.ctx.stroke();
            }
        }
        canvaslock.prototype.reset = function(){
            this.createcircle();
        }
})();