canvas 实现手机图案解锁

参考☞: https://www.cnblogs.com/chenyingying0/

先上效果图:

 

我是在 vue 里面实现js 文件 ,所以如果需要在vue 里面使用 可以将以下内容import '@/component/unlock', 这样直接引入就好,上代码

//component/unlock.js
(function() { // canvasLock是全局对象 window.canvasLock = function(obj) { this.width = obj.width this.height = obj.height this.circleNum = obj.circleNum ;(this.isOk = true), (this.errrorSum = '0') } //动态生成DOM canvasLock.prototype.initDom = function() { //创建一个div var div = document.createElement('div') let app = document.getElementById('app') var h4 = "
<h4 id='title' class='title'>绘制解锁图案</h4>" div.innerHTML = h4 div.id = 'unlock' div.setAttribute( 'style', 'position:absolute;top:0;left:0;right:0;bottom:0;' ) //创建canvas var canvas = document.createElement('canvas') canvas.setAttribute('id', 'canvas') //cssText 的本质就是设置 HTML 元素的 style 属性值 canvas.style.cssText = 'background:#2d3a4b;display:inine-block;margin-top:15px;' div.appendChild(canvas) app.appendChild(div) //设置canvas默认宽高 var width = this.width || 300 var height = this.height || 300 canvas.style.width = width + 'px' canvas.style.height = height + 'px' canvas.width = width canvas.height = height } //以给定坐标点为圆心画出单个圆 canvasLock.prototype.drawCircle = function(x, y) { this.ctx.strokeStyle = '#abcdef' this.ctx.lineWidth = 2 this.ctx.beginPath() this.ctx.arc(x, y, this.r, 0, 2 * Math.PI, true) this.ctx.closePath() this.ctx.stroke() } //绘制出所有的圆 canvasLock.prototype.createCircle = function() { var n = this.circleNum //一行几个圆 var count = 0 this.r = this.canvas.width / (4 * n + 2) 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: (4 * j + 3) * r, y: (4 * i + 3) * r, index: count } this.arr.push(obj) this.restPoint.push(obj) } } //清屏 this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) for (var i = 0; i < this.arr.length; i++) { this.drawCircle(this.arr[i].x, this.arr[i].y) } } //添加事件 canvasLock.prototype.bindEvent = function() { var self = this this.canvas.addEventListener( 'touchstart', function(e) { var po = self.getPosition(e) //判断是否在圆内 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]) self.restPoint.splice(i, 1) break } } }, false ) this.canvas.addEventListener( 'touchmove', function(e) { 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.storePass = function() { if (this.checkPass()) { document.getElementById('title').innerHTML = '解锁成功' window.location.href = 'http://localhost:8080/home' this.drawStatusPoint('lightgreen') } else { this.errrorSum++ if (this.errrorSum === 5) { let num = 30 this.isOk = false let time = setInterval(() => { num-- document.getElementById('title').innerHTML = `${num}秒后方可继续解锁` if (num === 0) { document.getElementById('title').innerHTML = `绘制图案解锁` } }, 1000) setTimeout(() => { this.isOk = true this.errrorSum = 0 clearInterval(time) }, 30000) } else if (this.errrorSum < 5) { document.getElementById('title').innerHTML = '解锁失败' this.drawStatusPoint('orange') } } } //判断输入的密码 canvasLock.prototype.checkPass = function() { var p1 = '72943816', //成功的密码 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, 2 * Math.PI, true ) this.ctx.closePath() this.ctx.stroke() } } //程序全部结束后重置 canvasLock.prototype.reset = function() { this.createCircle() } //获取鼠标点击处离canvas的距离 canvasLock.prototype.getPosition = function(e) { 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) { if (this.isOk) { this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height) for (var i = 0; i < this.arr.length; i++) { this.drawCircle(this.arr[i].x, this.arr[i].y) } this.drawPoint() this.drawLine(po) //画线 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.lastPoint.push(this.restPoint[i]) this.restPoint.splice(i, 1) break } } } } //画实心圆 canvasLock.prototype.drawPoint = function() { for (var i = 0; i < this.lastPoint.length; i++) { this.ctx.fillStyle = '#abcdef' this.ctx.beginPath() this.ctx.arc( this.lastPoint[i].x, this.lastPoint[i].y, this.r / 2, 0, 2 * Math.PI, true ) this.ctx.closePath() this.ctx.fill() } } //画线 canvasLock.prototype.drawLine = function(po) { this.ctx.beginPath() this.lineWidth = 3 this.ctx.moveTo( this.lastPoint[0] ? this.lastPoint[0].x : '', this.lastPoint[0] ? 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.init = function() { this.initDom() this.canvas = document.getElementById('canvas') this.ctx = this.canvas.getContext('2d') this.touchFlag = false this.createCircle() this.bindEvent() } })() new canvasLock({ circleNum: 3 }).init()

使用的vue 文件

<template></template>
<script>
import '@/component/unlock'
export default {
  created() {
    document.getElementById('unlock').style.display = 'block'
  },
  beforeDestroy() {
    document.getElementById('unlock').style.display = 'none'
  }
}
</script>
<style>
body {
  background: #2d3a4b;
  text-align: center;
}
</style>
原文地址:https://www.cnblogs.com/SuperBrother/p/12618107.html