vue2实现手势密码功能

本文实例为大家分享了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>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • atom-design(Vue.js移动端组件库)手势组件使用教程

    介绍 atom-design经过几个月的开发,以及这段时间的修复bug,对js,css压缩,按需引入处理等等的性能优化,现在已经逐渐完善.做这套UI考虑到很多性能的问题,以及如何让开发者更自由.更简单的去使用.这篇文章主要讲使用Gesture(手势)相关组件的感受. Gesture(手势)相关组件 •Carousel(传送带) •SlideItem (滑动条) •Range (区域选择) •Pull Gesture (上下拉动手势) Carousel(传送带) import {Carousel}

  • vue-router 手势滑动触发返回功能

    vue-router的路由变换只存在"变换前"和"变换后",不存在"切换中"的状态,所以做不到大多数app(微信那样的)在滑动过程中让界面跟随手指移动.但滑动事件还是可以监听的,我们可以在滑动之后再触发路由回退事件. 微博的滑动返回基本上就是这样的原理:先滑动.再触发返回事件,但用起来很是怪异,有严重的滞后感.夸克浏览器做的就比较好:一是滑动时界面虽然不动,但是界面上有小图标提示,能让用户接受到反馈:二是返回过程很快,没有多余的过渡动画. app

  • vue-drawer-layout实现手势滑出菜单栏

    本文实例为大家分享了vue-drawer-layout实现手势滑出菜单栏的具体代码,供大家参考,具体内容如下 文档链接地址 安装 npm install vue-drawer-layout --save main.js导入 import DrawerLayout from 'vue-drawer-layout' Vue.use(DrawerLayout) 完整代码 <template> <div class="box"> <vue-drawer-layou

  • vue2实现手势密码功能

    本文实例为大家分享了vue2实现手势密码功能的具体代码,供大家参考,具体内容如下 组件: <template>   <div class="masks" v-show="currentValue">     <div class="gesturePwd">       <div class="box">         <h4 ref="gestureTitle&

  • Android实现手势密码功能

    本文实例为大家分享了Android实现手势密码功能的具体代码,供大家参考,具体内容如下 首先声明一下,九宫格布局是从网上扒了一个大神写好的,大家在项目中实现的话可以直接把: Drawl,GuestureLockView,Point类直接复制到自己的项目中: 想了解功能的可以仔细看下源码中的这三个类,里面写的也非常详细: 使用GuestureLockView的三个步: 1.初始化布局容器: 2.初始化GuestureLockView; 3.将GuestureLockView添加到布局容器中: 创建

  • iOS实现手势密码功能

    手势密码实现 手势密码 一般常常用于金融项目,做的是安全相关的业务.具体实现如下思路,我把它分为view层和逻辑层.我将数据层合并到view层中了,最好是加上数据层用于处理加密的密码和密码的存储 view层 view层主要处理,包括(九个按钮)touchesBegan,touchesMoved,touchesEnded,点与点之间画线,手指滑动画线,画线主要是在drawRect中重绘,提到这里必须不能忘记setNeedsDisplay这个方法.还要记录经过的按钮btnsArray(存放按钮的数组

  • Android实现支付宝手势密码功能

    今天就给大家分享android实现支付宝手势密码,很常见,像现在用微信支付,支付宝支付的时候都要自己设置的4位PIN码,然后输入PIN码后立即调用支付接口去支付,毫无疑问的安全问题,不会觉得手机被人拿了后却不知道自己网银的钱的去向,这也是正常安全逻辑性问题. 好,下面我们来看下具体的实现: 入口,启动页面就简单的几个按钮,布局贴出来,代码如下: <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android

  • Android手势密码--设置和校验功能的实现代码

    效果图如下,大家感觉不错请参考实现代码 具体代码如下所示: private void setGesturePassword() { toggleMore.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { if (isChecke

  • 基于Flutter实现手势密码加密与解锁功能

    目录 前言 1.绘制静态图形 2.存储手势密码数据 3.添加手势交互 4.绘制.刷新密码线 5.加入密码错误动画 总结 前言 密码的由来:在公元前405年,由古希腊和斯巴达的战争中,由于斯巴达盟友波斯帝国背叛,导致古希腊和斯巴达两败俱伤,这时斯巴达抓了一个波斯国的信使,这个信使 没有任何情报,只有一条有着杂乱无章的希腊字母的普通腰带,最终斯巴达统帅破解了这条腰带,成功击败了希腊.这就是世界上最早的密码.同时也是世界上最早的解密. 密码在我们生活中无处不在,作为个人隐私的最后一道防线显得无比的重要

  • Android仿支付宝手势密码解锁功能

    Starting 创建手势密码可以查看 CreateGestureActivity.java 文件. 登陆验证手势密码可以看 GestureLoginActivity.java 文件. Features 使用了 JakeWharton/butterknife butterknife 使用了 ACache 来存储手势密码 /** * 保存手势密码 */ private void saveChosenPattern(List<LockPatternView.Cell> cells) { byte[

  • iOS手势密码的实现方法

    本次讲的手势密码,是在九个按键上实现的,这里讲的是手势密码的基本实现和效果 同样先上效果图 其实就是对画图功能的一个实现,再加上手势操作结合起来. 屏幕宽度高度,方便下面操作,不做解释 #define ScreenHeight [[UIScreen mainScreen] bounds].size.height #define ScreenWidth [[UIScreen mainScreen] bounds].size.width 控制器.m文件 这里的imageView是用来装手势画图之后的

  • Android 简易手势密码开源库详解

    简介 本文介绍一个Android手势密码开源库的使用及实现的详细过程,该开源库主要实现以下几个功能: 支持手势密码的绘制,并支持密码保存功能,解锁时自动比对密码给出结果 封装了绘制密码的方法,比对两次密码是否一致,可以快捷地进行手势密码的设置 可以设置密码输入错误后的重试次数上限 可以自定义不同状态下手势密码图案的颜色 可以自定义手势密码的触摸点数量(n*n) 最近需要用到手势密码解锁功能,找了一些demo感觉用起来都有点麻烦,于是参考一些文章自己造了下轮子,封装了相关的一些方法,使用起来比较便

  • Android 5秒学会使用手势解锁功能

    Android手势解锁 本文讲述的是一个手势解锁的库,可以定制显示隐藏宫格点.路径.并且带有小九宫格显示图,和震动!让你学会使用这个简单,高效的库! 先来一波效果效果展示: 手势解锁效果 今天给大家介绍的是本人良心制作的一个手势解锁开源库,大家有什么建议和想法都可以发到我的邮箱: diosamolee2014@gmail.com 或者评论,我会为大家提供我力所能及的帮助! GitHub地址: https://github.com/Diosamo/Gesture_Lock 添加依赖: 添加的gra

随机推荐