<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>手机解锁</title> <meta name="viewport" content="width=device-width,initial-scale=1.0,user-scalable=no" /> <style> body{ text-align: center; background: #305066; } h4{ color: #22c3aa; } </style> </head> <body> <script type="text/javascript" src="js/index.js"></script> <script> //1.生成背景 //2.动态title生成 //3.用js动态生成canvas标签 //4.js动态生成h3标签和canvas标签 new canvasLock({chooseType:3}).init(); </script> </body> </html>
(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 = '#cfe6ef'; 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(){ //创建点的坐标,根据c var n = this.chooseType; //n是指有几行圆 var count = 0; this.r = this.ctx.canvas.width / (2+4*n); //圆心坐标 this.lastPoint = []; this.arr = []; //9个圆的中心点坐标 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); } } //程序初始化 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; //一个是canvas对象,一个是window.canvasLock对象 console.log(this); //如果直接使用this,那么this指向的就是当前时间调用的对象,也就是this.canvas, console.log(self); //但是在代码中想要使用的是window.canvasLock对象,所以在事件外面提前将this赋值给self变量,确保this的指向问题。 this.canvas.addEventListener('touchstart',function(e){ //2.touchstart判断是否点击的位置处于园内getPosition,处于则初始化lastpoint、restPoint var po = self.getPosition(e); //判断是否在圆内的原理:多出来的这条 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; self.lastPoint.push(self.arr[i]); //把点击的圆心的x轴y轴坐标放入lastPoint数组 console.log(self.lastPoint); self.restPoint.splice(i,1); break; } } },false); this.canvas.addEventListener('touchmove',function(e){ // 3.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 //获取canvas上下左右离屏幕的距离 var rect = e.currentTarget.getBoundingClientRect(); // Element.getBoundingClientRect()方法返回元素的大小及其相对于视口的位置。 //po有x和y,并且使相较于canvas边距 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); //画完一个圆就将该圆从restPoint数组中去掉 break; } } } 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 = '#cfe6fe'; 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(); } } 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(); } })();