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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM