zoukankan      html  css  js  c++  java
  • vue中canvas 实现手势密码

    思路:

    手势密码思路:
    1 使用canvas 画圆和线条
    2 使用canvas画一个画布 设置画布的宽高 CW CH,获取画布距离页面的位置信息canvas.getBoundingClientRect()

    3 设置画板距离canvas两边和顶部的距离 offetX offsetY
    4 九宫格每个圆是一样大小的,设置圆的半径R
    5 获取圆左右之间的间距 (CW-offsetX*2-3*2*R)/2 diffX
    6 获取圆上下之间的间距(CH-offsetY*2-3*2*R)/2 diffY
    7 画圆
    7.1 带蓝色边框的空心圆,原理是先画一个蓝色的实心圆,再在同一个圆心处画一个实心的白色圆圈(半径比蓝色的圆小,两个圆之间的差距就是边框的大小)
    7.2 获取每个圆圆心的位置信息数组:Re=[],3*3的九宫格,双层循环“
    for(var row=0; row<3;row++){
    for(var col=0; col<3;col++){
    var point={
    x:offsetX+(1+col*2)*R+diffX*col
    y:offsetY+(1+row*2)*R+diffY*row
    }
    }
    Re.push(point);
    }
    7.3 画外围蓝色实心的圆,再画实心白色圆,实现带蓝色边框的圆
    8 监听touch事件 touchstart touchmove touchend
    9 在touchstart判断起点是否在圆中,如果在把圆心的位置信息放在pointline数组中,touchesmove中开始画线(判断touch点是否在圆点内部,如果在,开始画线,从连线的第一点开始,画线完成之后开始重新画圆(重复7 的步骤),画圆中判断其中的点是否在手势路线中,如果在就画圆心,最后一步,把最后一个点与当前的手势所在的位置连在一起;

    10 touchesend中,判断密码长度是否大于4,与原始密码进行对比,如果不对就改变颜色,重新画九宫格,到最后一个点就可以了,不需要连接最后一个点与结束时手势所在的位置

    demo:

    <template>
    <canvas ref='myCanvas'></canvas>
    </template>
    <script>
    export default{
      data(){
        return{
          c:'',
          cPosition:{},
          cxt:'',
          CW:600,
          CH:320,
          Radius:25,
          offsetX:40,
          offsetY:30,
          password:[0,1,2,3,4],
          successColor:'#627eed',
          errorColor:'red',
          innerColor:'',
          successInnerColor:'#ffffff',
          errorInnerColor:'#ffffff',
          selectColor:'',
          Re:[],
          borderWidth:1,
          pointLine:[],
          pointWidth:8,//圆心的半径大小
          lineWidth:3//连线的大小
        }
      },
      mounted(){
        let _this=this;
        this.selectColor=this.successColor;
        this.innerColor=this.successInnerColor;
         this.$nextTick(function(){
          _this.init();
          _this.initEvent();
         });
      },
      methods:{
        init(){
          this.initCas();
          this.getPointLocationArr();
          this.draw();
        },
        initCas(){//初始化画布
           this.c=this.$refs.myCanvas;
            this.CW=document.body.offsetWidth;
            this.c.width=this.CW;
            this.c.height=this.CH;
            this.cPosition=this.c.getBoundingClientRect();
            this.cxt=this.c.getContext('2d');
        },
        getPointLocationArr(){//获取九宫格圆心位置信息
          //获取圆点之间的间距
          let diffX=(this.CW-this.offsetX*2-this.Radius*2*3)/2;
          let diffY=(this.CH-this.offsetY*2-this.Radius*2*3)/2;
          for(let row=0;row<3;row++){
            for(let col=0; col<3;col++){
              let point={
                x:this.offsetX+col*diffX+(col*2+1)*this.Radius,
                y:this.offsetY+row*diffY+(row*2+1)*this.Radius
              }
              this.Re.push(point);
            }
          }
        },
        drawPoint(touches,touchPoint){//选中的圆画圆心并连接起来
        let pointLine=this.pointLine;
        this.cxt.beginPath();
          for(let i=0; i<pointLine.length;i++){
            let point=this.Re[pointLine[i]];//根据存储的圆点的下标找到圆点的圆心位置
            //连接选中的点begin
            this.cxt.lineTo(point.x,point.y);
          }
           this.cxt.strokeStyle=this.selectColor;
            this.cxt.lineWidth=this.lineWidth;
            this.cxt.stroke();
            this.cxt.closePath();
            if(touchPoint){
              let lastPoint=this.Re[this.pointLine[this.pointLine.length-1]];
              this.cxt.beginPath();
              this.cxt.moveTo(lastPoint.x,lastPoint.y);
              this.cxt.lineTo(touches.pageX-this.cPosition.left,touches.pageY-this.cPosition.top);
             this.cxt.strokeStyle=this.selectColor;
            this.cxt.lineWidth=this.lineWidth;
            this.cxt.stroke();
            this.cxt.closePath();
            }
    
        },
        isPointSelect(touchs){//圆点是否被选中
        let Re=this.Re;
          for(let i=0;i<Re.length;i++){
            let currentPonit=Re[i];
            let xdiff=Math.abs(touchs.pageX-currentPonit.x-this.cPosition.left);
             let ydiff=Math.abs(touchs.pageY-currentPonit.y-this.cPosition.top);
             let dir=Math.pow(xdiff*xdiff+ydiff*ydiff,0.5);//当前鼠标的位置与圆心之间的距离两边和的开方
             if(dir<=this.Radius){
               if(this.pointLine.indexOf(i)==-1){
               this.pointLine.push(i);
             }
             break;
          }
          }
    
        },
        initEvent(){
          let _this=this;
          this.c.addEventListener('touchstart',function(e){
            _this.isPointSelect(e.touches[0]);
          });
          this.c.addEventListener('touchmove',function(e){
             _this.isPointSelect(e.touches[0]);
             //清空画布
             _this.cxt.clearRect(0,0,_this.CW,_this.CH);
             _this.draw(e.touches[0],true);
    
          });
          this.c.addEventListener('touchend',function(e){
            if(_this.pointLine.length<4){
              alert('密码长度不能小于4!');
              _this.selectColor=_this.errorColor;
              _this.innerColor=_this.errorInnerColor;
            }
            _this.checkIsRight();
             //清空画布
             _this.cxt.clearRect(0,0,_this.CW,_this.CH);
             _this.draw(e.touches[0],false);
            _this.resetCxt(e.touches[0]);
            
          });
        },
        resetCxt(touches){
          let _this=this;
          setTimeout(()=>{
              this.pointLine=[];
              this.selectColor=this.successColor;
              this.innerColor=this.successInnerColor;
              this.cxt.clearRect(0,0,_this.CW,_this.CH);
              this.draw(touches,false);
          },3000);
        },
        checkIsRight(){
          if(this.password.toString()!=this.pointLine.toString()){
             this.selectColor=this.errorColor;
            this.innerColor=this.errorInnerColor;
          }
        },
        draw(touches,touchPonit){
          //画九宫格
          if(this.pointLine.length>0)
          this.drawPoint(touches,touchPonit);
          let Re=this.Re;
          for(let i=0; i<Re.length;i++){
            let point=Re[i];
            //画外层蓝色的圆
            this.cxt.fillStyle=this.selectColor;
            this.cxt.beginPath();
            this.cxt.arc(point.x,point.y,this.Radius,0,2*Math.PI,true);//圆心x坐标,y坐标,圆的半径,从0 画到360,逆时针画图
            this.cxt.fill();
            this.cxt.closePath();
            //画内部白色的圆
            this.cxt.fillStyle=this.innerColor;
            this.cxt.beginPath();
            this.cxt.arc(point.x,point.y,this.Radius-this.borderWidth,0,2*Math.PI,true);
             this.cxt.fill();
            this.cxt.closePath();
            //画选中圆点的圆心
          if(this.pointLine.indexOf(i)!=-1){
            //画选中的点begin
            this.cxt.fillStyle=this.selectColor;
            this.cxt.beginPath();
            this.cxt.arc(point.x,point.y,this.pointWidth,0,2*Math.PI,true);
            this.cxt.fill();
            this.cxt.closePath();
            //画选中的点end
          }
    
          }
    
        }
    
      }
    }
    </script>

    1 初始画布:

     密码长度小于4:

     关闭弹框

     密码错误

     密码正确

     圆与圆之间的间距

    参考:https://www.cnblogs.com/wuyufei/p/11996831.html

  • 相关阅读:
    Docker学习-安装,配置,运行
    Docker学习-从无知到有知的学习过程
    学习记录-java基础部分(一)
    对get post等http请求方式的理解
    Mac和window实现双向数据传输
    git pull时 git cannot lock ref XXXXXX (unable to update local ref)错误解决方案
    三年内我的计划和方向
    关于云服务器和云部署的实操(新手级别入门)
    win7蓝屏死机0x0000003B错误蓝屏故障解决
    JAVA代码:生成一个集合,自定义大小,100以内的随机整数
  • 原文地址:https://www.cnblogs.com/xiaofenguo/p/12858785.html
Copyright © 2011-2022 走看看