vue2实现手势密码功能

Laila ·
更新时间:2024-11-15
· 313 次阅读

本文实例为大家分享了vue2实现手势密码功能的具体代码,供大家参考,具体内容如下

组件:

<template>   <div class="masks" v-show="currentValue">     <div class="gesturePwd">       <div class="box">         <h4 ref="gestureTitle" class="gestureTitle">请绘制您的图形密码</h4>         <a class="reset" ref="updatePassword" @click="updatePassword()">重置密码</a>         <a class="close" ref="updatePassword" @click="closePwd(false)">关闭</a>         <canvas ref="canvas"></canvas>       </div>     </div>   </div> </template> <script>   export default {     props: {       value: {         type: Boolean,         default: false       },     },     data() {       return {         currentValue: false,         ctx: '',         width: 0,         height: 0,         devicePixelRatio: 0,         chooseType: '',         r: '',// 公式计算         lastPoint: [],         arr: [],         restPoint: [],         pswObj: {step: 2},         canvas: ''       }     },     watch: {       value: {         handler: function (val) {           this.currentValue = val         },         immediate: true       },       currentValue(val) {         this.$emit(val ? 'on-show' : 'on-hide')         this.$emit('input', val)       }     },     created() {       if (typeof this.value !== 'undefined') {         this.currentValue = this.value       }     },     mounted() {       this.setChooseType(3);     },     methods: {       closePwd(bol) {         this.$emit("handPwd",bol);         this.currentValue = false;       },       drawCle(x, y) { // 初始化解锁密码面板 小圆圈         this.ctx.strokeStyle = '#87888a';//密码的点点默认的颜色         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();       },       drawPoint(style) { // 初始化圆心         for (var i = 0; i < this.lastPoint.length; i++) {           this.ctx.fillStyle = style;           this.ctx.beginPath();           this.ctx.arc(this.lastPoint[i].x, this.lastPoint[i].y, this.r / 2.5, 0, Math.PI * 2, true);           this.ctx.closePath();           this.ctx.fill();         }       },       drawStatusPoint(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();         }       },       drawLine(style, po, lastPoint) {//style:颜色 解锁轨迹         this.ctx.beginPath();         this.ctx.strokeStyle = style;         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();       },       createCircle() {// 创建解锁点的坐标,根据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);         }       },       getPosition(e) {// 获取touch点相对于canvas的坐标         var rect = e.currentTarget.getBoundingClientRect();         var po = {           x: (e.touches[0].clientX - rect.left) * this.devicePixelRatio,           y: (e.touches[0].clientY - rect.top) * this.devicePixelRatio         };         return po;       },       update(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('#27AED5');// 每帧花轨迹         this.drawStatusPoint('#27AED5');// 每帧花轨迹         this.drawLine('#27AED5', po, this.lastPoint);// 每帧画圆心         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]);             this.restPoint.splice(i, 1);             break;           }         }       },       checkPass(psw1, psw2) {// 检测密码         var p1 = '', p2 = '';         for (var i = 0; i < psw1.length; i++) {           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;       },       storePass(psw) {// touchend结束之后对密码和状态的处理         if (this.pswObj.step == 1) {           if (this.checkPass(this.pswObj.fpassword, psw)) {             this.pswObj.step = 2;             this.pswObj.spassword = psw;             this.$refs.gestureTitle.innerHTML = '密码保存成功';             this.drawStatusPoint('#2CFF26');             this.drawPoint('#2CFF26');             window.localStorage.setItem('passwordxx', JSON.stringify(this.pswObj.spassword));             window.localStorage.setItem('chooseType', this.chooseType);           } else {             this.$refs.gestureTitle.innerHTML = '两次不一致,重新输入';             this.drawStatusPoint('red');             this.drawPoint('red');             delete this.pswObj.step;           }         } else if (this.pswObj.step == 2) {           if (this.checkPass(this.pswObj.spassword, psw)) {             var gestureTitle = this.$refs.gestureTitle;             gestureTitle.style.color = "#2CFF26";             gestureTitle.innerHTML = '解锁成功';             this.drawStatusPoint('#2CFF26');//小点点外圈高亮             this.drawPoint('#2CFF26');             this.drawLine('#2CFF26', this.lastPoint[this.lastPoint.length - 1], this.lastPoint);// 每帧画圆心             this.closePwd(true);           } else if (psw.length < 4) {             this.drawStatusPoint('red');             this.drawPoint('red');             this.drawLine('red', this.lastPoint[this.lastPoint.length - 1], this.lastPoint);// 每帧画圆心             var gestureTitle = this.$refs.gestureTitle;             gestureTitle.style.color = "red";             gestureTitle.innerHTML = '请连接4个点';           } else {             this.drawStatusPoint('red');             this.drawPoint('red');             this.drawLine('red', this.lastPoint[this.lastPoint.length - 1], this.lastPoint);// 每帧画圆心             var gestureTitle = this.$refs.gestureTitle;             gestureTitle.style.color = "red";             gestureTitle.innerHTML = '密码错误';           }         } else {           this.pswObj.step = 1;           this.pswObj.fpassword = psw;           this.$refs.gestureTitle.innerHTML = '再次输入';         }       },       makeState() {         if (this.pswObj.step == 2) {           this.$refs.updatePassword.style.display = 'block';           var gestureTitle = this.$refs.gestureTitle;           gestureTitle.style.color = "#87888a";           gestureTitle.innerHTML = '请解锁';         } else if (this.pswObj.step == 1) {           this.$refs.updatePassword.style.display = 'none';         } else {           this.$refs.updatePassword.style.display = 'block';         }       },       setChooseType(type) {         this.chooseType = type;         this.init();       },       updatePassword() {         window.localStorage.removeItem('passwordxx');         window.localStorage.removeItem('chooseType');         this.pswObj = {};         this.$refs.gestureTitle.innerHTML = '绘制解锁图案';         this.reset();       },       initDom() {         this.chooseType = Number(window.localStorage.getItem('chooseType')) || 3;         this.devicePixelRatio = window.devicePixelRatio || 1;         var canvas = this.$refs.canvas;         var width = this.width || 320;         var height = this.height || 320;         // 高清屏锁放         canvas.style.width = width + "px";         canvas.style.height = height + "px";         canvas.height = height * this.devicePixelRatio;         canvas.width = width * this.devicePixelRatio;       },       init() {         this.initDom();         this.pswObj = window.localStorage.getItem('passwordxx') ? {           step: 2,           spassword: JSON.parse(window.localStorage.getItem('passwordxx'))         } : {};         this.lastPoint = [];         this.makeState();         this.touchFlag = false;         this.canvas = this.$refs.canvas;         this.ctx = this.canvas.getContext('2d');         this.createCircle();         this.bindEvent();       },       reset() {         this.makeState();         this.createCircle();       },       bindEvent() {         var self = this;         this.canvas = this.$refs.canvas;         this.canvas.addEventListener("touchstart", function (e) {           e.preventDefault();// 某些android 的 touchmove不宜触发 所以增加此行代码           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.drawPoint(self.arr[i].x, self.arr[i].y);               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.touchFlag = false;             self.storePass(self.lastPoint);             setTimeout(function () {               self.reset();             }, 1000);           }         }, false);       }     }   } </script> <style scoped>   .masks {     text-align: center;     position: fixed;     z-index: 1000;     top: 0;     right: 0;     left: 0;     bottom: 0;     background: rgba(0, 0, 0, 0.6);   }   .gesturePwd {     position: fixed;     z-index: 5000;     width: 100%;     height: 100%;     top: 50%;     left: 50%;     -webkit-transform: translate(-50%, -50%);     transform: translate(-50%, -50%);     text-align: center;     border-radius: 3px;     overflow: hidden;     background-color: #000;   }   .gestureTitle {     color: #87888a;     margin-top: 85px;     font-size: 20px;     font-weight: normal;   }   .box{     position: absolute;     top:0;     left:0;     right:0;     bottom:0;   }   .box a{     position: absolute;     top: 5px;     color:#fff;     font-size: 13px;     display:block;   }   a.reset{     left: 5px;   }   a.close{     right :5px;   }   .box canvas{     background-color: #000;     display: inline-block;     margin-top: 76px;     width: 320px;     height: 320px;   } </style>

调用:

<template>   <div class="hello">     <button @click="showClicked" style="width:90px;height:50px;font-size:16px;background-color:#eee">手势密码</button>     <pwd v-model="showPwd" @handPwd="handPwd"></pwd>   </div> </template> <script>   import pwd from '@/components/pwd'   export default {     name: 'hello',     data() {       return {         showPwd: false       }     },     methods: {       showClicked() {         this.showPwd = true;       },       handPwd(val) {         console.log(val);       }     },     components: {       pwd     },   } </script>



VUE 手势

需要 登录 后方可回复, 如果你还没有账号请 注册新账号