canvas实现一个解锁demo

编程入门 行业动态 更新时间:2024-10-23 22:30:07

canvas实现一个<a href=https://www.elefans.com/category/jswz/34/1771119.html style=解锁demo"/>

canvas实现一个解锁demo

问题1:

代码如下:

function Foo() {};
Foo.prototype.talk = function () {alert('hello~\n');
};var a = new Foo;
a.talk(); // 输出'hello~\n'

但是如果这样:

Foo.talk() // 报错:Object doesn't support property or method 'talk'
Foo.prototype.talk() // 没有问题

解答:

因为这里a是构造出来的对象,其[[proto]]属性指向Foo.prototype。但Foo不是,Foo是一个函数对象,它的[[proto]]指向的是Function.prototype,因此有的是Foo.call Foo.apply这些函数对象上的方法(来自Function.prototypr)而不会有你定义的那个talk


问题2:

对一个函数对象添加属性,用prototype何不用prototype有何不同

用prototype添加属性的时候,当你实例化以后调用实际上只是调用了原型对象,只调用了一次,不管你实例化几次最多只是内容变了,而在内存中只会出现一次原型对象的函数。



js完成dom结构


tips: setAttribute和.style方法


setAttribute是给html元素属性设置值的。html元素属性就是指的标签中的键值对的前者,
例如<div id="name" class="text"><div>中的id和class就是html元素属性。

.style.property="值"是用来设置css样式的。例如说
document.getElementById("#name").style.background="red"设置文本框的背景颜色为红色。

在标签中我们也会内嵌样式,
例如<div id="name" class="text" style="width:100px;"><div>,说明style也是html元素的一个属性。
在设置的时候可以使用document.getElementById("#name").setAttribute("style","color:red;font:9px;");
实际上平时用setAtrribute()这个方法就用的不多,也不太支持这种设置样式属性的写法。
如果引用了jQuery的话,在设置CSS样式的时候还可以使用.css("border","1px solid red");这种方式。

 

H5lock.prototype.initDom = function(){var wrap = document.createElement('div');var str = '<h4 id="title" class="title">绘制解锁图案</h4>'+'<a id="updatePassword" style="position: absolute;right: 5px;top: 5px;color:#fff;font-size: 10px;display:none;">重置密码</a>';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.height = height * this.devicePixelRatio; //修改canvas默认宽高
    canvas.width = width * this.devicePixelRatio;}




画外层大圆的函数

关于大圆半径求法


如下图为一行三个圆的时候  






this.r = this.ctx.canvas.width / (2 + 4 * n);// 公式计算
把大圆的直径和大圆左侧距离看成一个整体 也就是    4个半径的长度   一行就是n个圆   4*n  加上最右剩余的距离两个半径     所以计算半径公式如上




实现存放大圆坐标

H5lock.prototype.createCircle = function() {// 创建解锁点的坐标,根据canvas的大小来平均分配半径

    var n = this.chooseType;var count = 0;this.r = this.ctx.canvas.width / (2 + 4 * n);// 公式计算

    //确定圆心
    this.lastPoint = [];this.arr = [];//9个圆的中心点坐标
    this.restPoint = [];//同样是9个圆
    var r = this.r;for (var i = 0 ; i < n ; i++) {//3*3


        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;
}



绘制圆  drawCle


H5lock.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();
}




绑定触摸事件


触发触摸:判断触摸点是否在大圆内  

判断方法  触发点到画布最左的距离 减去 大圆圆心到最左的距离 的绝对值小于半径   那么这个触发点一定在某个圆内   有九个大圆 所以得遍历比较每个圆  遇到满足条件的就终止循环



this.canvas.addEventListener("touchstart", function (e) {//判断触发点是不是再大圆内
    e.preventDefault();// 某些android 的 touchmove不宜触发 所以增加此行代码
     var po = self.getPosition(e);//判断触摸点位置
     console.log(po);//判断条件 触发点与圆心的位置到最左端的绝对值是否小于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;self.drawPoint(self.arr[i].x,self.arr[i].y);self.lastPoint.push(self.arr[i]);//点在哪个圆内就往lastpoint中push哪个圆的坐标
            self.restPoint.splice(i,1);break;//每次都要从第一个圆开始判断直到最后一个圆  如果中间判断出在某个圆内  就要终止循环
        }}}, false);


获取触发点坐标的函数getPosition


//判断触摸点位置的函数
H5lock.prototype.getPosition = function(e) {// 获取touch点相对于canvas的坐标
    var rect = e.currentTarget.getBoundingClientRect();//返回的是画布距离屏幕的上下左右距离
    var po = {x: (e.touches[0].clientX - rect.left)*this.devicePixelRatio,//一个手指操作 所以 下标为0  注意这里是触发点到屏幕左的距离减去画布到屏幕左的距离
        y: (e.touches[0].clientY - rect.top)*this.devicePixelRatio
      };return po;
}

补充

getBoundingClientRect用于获取某个元素相对于视窗的位置集合。集合中有top, right, bottom, left等属性。

 rectObject.top:元素上边到视窗上边的距离;

 rectObject.right:元素右边到视窗左边的距离;

 rectObject.bottom:元素下边到视窗上边的距离;

 rectObject.left:元素左边到视窗左边的距离;



clientX  、 clientY

clientX 事件属性返回当事件被触发时鼠标指针向对于浏览器页面(或客户区)的水平坐标。



touches

这是应用于移动端触摸事件的,event.x是他在手机上点的X轴位置,event.touches,多点触碰时的位置数组,比如缩放手势必须要用两指的触摸点,就是一个数组



添加touchmove事件

this.canvas.addEventListener("touchmove", function (e) {//画圆和画线
   if (self.touchFlag) {self.update(self.getPosition(e));}
}, false);

update函数


H5lock.prototype.update = function(po) {// 核心变换方法在touchmove时候调用
    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);}this.drawPoint(this.lastPoint);// 每帧画圆心
    this.drawLine(po , this.lastPoint);// 每帧花轨迹


    //1.检测手势移动的位置是否处于下一个圆内
    //2.如果处于圆内则画圆
    //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.restPoint[i].x, this.restPoint[i].y);this.lastPoint.push(this.restPoint[i]);//上面是找到画过内圆的 大圆  然后从restPoint中删除掉这个
            this.restPoint.splice(i, 1);break;}}}画内圆的函数   drawPoint
H5lock.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();}
}


画线段的函数   drawLine

H5lock.prototype.drawLine = function(po, lastPoint) {// 解锁轨迹
    this.ctx.beginPath();this.ctx.lineWidth = 3;this.ctx.moveTo(this.lastPoint[0].x, this.lastPoint[0].y);//起始点为圆心
    console.log(this.lastPoint.length);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();}


继续添加touchend事件

this.canvas.addEventListener("touchend", function (e) {if (self.touchFlag) {self.touchFlag = false;self.storePass(self.lastPoint);setTimeout(function(){self.reset();
//不管密码输入正确与否  过了一会要将页面重置为开始时的九个无状态的大圆
}, 300); }}, false);

tips:

setTimeout(表达式,延时时间)在执行时,是在载入后延迟指定时间后,去执行一次表达式,记住,次数是一次 而setInterval(表达式,交互时间)则不一样,它从载入后,每隔指定的时间就执行一次表达式 



存储密码函数 storePass

H5lock.prototype.storePass = function(psw) {// touchend结束之后对密码和状态的处理
    if (this.pswObj.step == 1) {if (this.checkPass(this.pswObj.fpassword, psw)) {this.pswObj.step = 2;this.pswObj.spassword = psw;document.getElementById('title').innerHTML = '密码保存成功';this.drawStatusPoint('#2CFF26');window.localStorage.setItem('passwordxx', JSON.stringify(this.pswObj.spassword));window.localStorage.setItem('chooseType', this.chooseType);} else {document.getElementById('title').innerHTML = '两次不一致,重新输入';this.drawStatusPoint('red');delete this.pswObj.step;}} else if (this.pswObj.step == 2) {if (this.checkPass(this.pswObj.spassword, psw)) {document.getElementById('title').innerHTML = '解锁成功';this.drawStatusPoint('#2CFF26');} else {this.drawStatusPoint('red');document.getElementById('title').innerHTML = '解锁失败';}} else {//第一次输入的时候会直接执行这一段  
        this.pswObj.step = 1;this.pswObj.fpassword = psw;document.getElementById('title').innerHTML = '再次输入';}}

检测密码checkPass

/*检测解锁成功:
1.检测路径是否正确
2.正确就重置,圆圈变绿
3.不对也重置,圆圈变红
4.重置

*/H5lock.prototype.checkPass = function(psw1, psw2) {// 检测密码
    var p1 = '',//成功解锁的密码
    p2 = '';for (var i = 0 ; i < psw1.length ; i++) {//index是九个点  分别为1 ~9 
        p1 += psw1[i].index + psw1[i].index;}for (var i = 0 ; i < psw2.length ; i++) {p2 += psw2[i].index + psw2[i].index;}return p1 === p2;//返回的是布尔值
}
注意psw都是数组drawStatusPoint是重绘大圆颜色的 
正确是绿色  错误是红色
H5lock.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();}
}


reset重置

H5lock.prototype.reset = function() {this.makeState();this.createCircle();//重新画出最开的九个圆
}


makeState

H5lock.prototype.makeState = function() {//决定右上角的重置密码这几个字是否显示
    if (this.pswObj.step == 2) {//如果在设置密码的时候 第二次输入的密码与第一次不符 根本不会有等于2的情况
        document.getElementById('updatePassword').style.display = 'block';//document.getElementById('chooseType').style.display = 'none';
        document.getElementById('title').innerHTML = '请解锁';} else if (this.pswObj.step == 1) {//document.getElementById('chooseType').style.display = 'none';
        document.getElementById('updatePassword').style.display = 'none';} else {document.getElementById('updatePassword').style.display = 'none'; //点击重置密码的时候触发这里//document.getElementById('chooseType').style.display = 'block';
    }
}



给重置密码这个div绑定一个点击事件

document.getElementById('updatePassword').addEventListener('click', function(){self.updatePassword();});




updatePassword

H5lock.prototype.updatePassword = function(){window.localStorage.removeItem('passwordxx');window.localStorage.removeItem('chooseType');this.pswObj = {};//step被删除  document.getElementById('title').innerHTML = '绘制解锁图案';this.reset();
}



初始化
H5lock.prototype.init = function() {//1.确定半径
    //2.确定每个圆的中心坐标
    //3.    14个半径
    this.initDom();this.pswObj = window.localStorage.getItem('passwordxx') ? {step: 2,spassword: JSON.parse(window.localStorage.getItem('passwordxx'))} : {};this.lastPoint = [];this.makeState();//决定重置密码这几个字是否显示
    this.touchFlag = false;//初始化touchFlag
    this.canvas = document.getElementById('canvas');this.ctx = this.canvas.getContext('2d');this.createCircle();//大圆绘制
    this.bindEvent();//绑定事件函数
}

 

更多推荐

canvas实现一个解锁demo

本文发布于:2024-03-08 07:34:26,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1720221.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:解锁   canvas   demo

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!