1. 程式人生 > 其它 >React => js+canvas四位數字字母混合驗證碼(數字+大寫字母+小寫字母)

React => js+canvas四位數字字母混合驗證碼(數字+大寫字母+小寫字母)

技術標籤:cssjavascriptcanvasreact

文章目錄

此為最終實現效果!

在這裡插入圖片描述
點選圖片可切換驗證碼
在這裡插入圖片描述

開始進行編寫

html新增canvas標籤

  <canvas
          onClick={this.reloadPic} //點選切換事件
ref={this.canvas} //ref含義下面講解 width="100" height="40" //設定高度寬度 ></canvas>

ref講解

元件內的標籤都可以定義 ref 屬性來標識自己
1.通過React.createRef()建立Refs並通過ref屬性聯絡到React元件
2.當一個ref通過render放入一個元素中,一個對節點的引用可以通過ref的current屬性得到

頁面初始化生成驗證碼

//頁面初始化後獲取canvas元件,並在canvas元件內生成驗證碼
componentWillMount() { this.canvas = React.createRef(); } componentDidMount() { this.randomCode(); } ### 設定初始值 ```javascript constructor(props) { super(props); this.state = { code: "", codeLength: 4,//驗證碼長度 contentWidth: 96, contentHeight: 38
,//內容高度/寬頻 showError: false, }; }

設定生死成隨機數函式 randomNum()

  //生成一個隨機數
  randomNum = (min, max) => {
    return Math.floor(Math.random() * (max - min) + min);
  };
 
  //生成一個隨機顏色
  randomColor(min, max) {
    const r = this.randomNum(min, max);
    const g = this.randomNum(min, max);
    const b = this.randomNum(min, max);
    return `rgb(${r}, ${g}, ${b})`;
  }

設定干擾線函式drawLine()

具體繪製請看下面 ->繪製路徑(path)

    // 繪製干擾線
  drawLine(ctx) {
    for (let i = 0; i < 1; i++) {
      ctx.strokeStyle = this.randomColor(40,180);
      //strokeStyle = color 設定圖形輪廓的顏色
      ctx.beginPath();
      ctx.moveTo(
        this.randomNum(0, this.state.contentWidth),
        this.randomNum(0, this.state.contentHeight)
      );
      ctx.lineTo(
        this.randomNum(0, this.state.contentWidth),
        this.randomNum(0, this.state.contentHeight)
      );
      ctx.stroke();
    }
  }

  //繪製干擾點
  drawDot(ctx) {
    for (let i = 0; i < this.state.contentWidth/4; i++) {
      ctx.fillStyle = this.randomColor(0, 255);
      //fillStyle = color 設定圖形的填充顏色
      ctx.beginPath();
      ctx.arc(
        this.randomNum(0, this.state.contentWidth),
        this.randomNum(0, this.state.contentHeight),
        1,
        0,
        2 * Math.PI
      );
      ctx.fill();
    }
  }

繪製路徑 (path)

使用路徑繪製圖形需要一些額外的步驟:
1.建立路徑起始點
2.呼叫繪製方法去繪製出路徑
3.把路徑封閉
4.一旦路徑生成,通過描邊或填充路徑區域來渲染圖形。

下面是需要用到的方法:
1.beginPath()

新建一條路徑,路徑一旦建立成功,圖形繪製命令被指向到路徑上生成路徑

2.moveTo(x, y)

把畫筆移動到指定的座標(x, y)。相當於設定路徑的起始點座標。

3.closePath()

閉合路徑之後,圖形繪製命令又重新指向到上下文中

4.stroke()

通過線條來繪製圖形輪廓

5.fill()

通過填充路徑的內容區域生成實心的圖形

設定生成字型顏色和大小及位置 drawText()

  drawText(ctx, txt, i) {
    //隨機生成字型顏色 呼叫隨機數函式
    ctx.fillStyle = this.randomColor(100, 200);
    //隨機生成字型大小字號 呼叫隨機數函式
    const fontSize = this.randomNum(10, 20);
    ctx.font = fontSize + "px SimHei"; //給字號加單位,生成字型

    //設定位置
    const padding = 10;
    //偏移量 
    const offset = (this.state.contentWidth - 40) (this.state.code.length - 1);
    let x = padding;
    if (i > 0) {
      x = padding + i * offset;
    }
    //呼叫隨機數函式
    let y = this.randomNum(20, this.state.contentHeight - 5);
    const deg = this.randomNum(-10, 10);
    
    // 設定座標原點和旋轉角度
    ctx.translate(x, y);
    ctx.rotate((deg * Math.PI) / 180);
    ctx.fillText(txt, 0, 0);
    
    // 恢復座標原點和旋轉角度
    ctx.rotate((-deg * Math.PI) / 180);
    ctx.translate(-x, -y);
  }

生成字母數字組合 randomCode()

  //生成字母數字陣列
  randomCode() {
    let random = "";
    const str = "QWERTYUPLKJHGFIODSAZXCVBNMqwlioertyupkjhgfdsazxcvbnm1234567890";
    for (let i = 0; i < this.state.codeLength; i++) {
      const index = Math.floor(Math.random() * 57);
      //取得隨機數的索引(0~57)
      random += str[index];
      //根據索引取得隨機數加到code上 
    }
   this.setState(
      {  code: random,//賦值給code  },
      () => {
        const canvas = this.canvas.current;
         //拿到canvas元件 如果不懂請看ref講解
        const ctx = canvas.getContext("2d");
       //getContext("2d") 物件是內建的 HTML5 物件
       //擁有多種繪製路徑、矩形、圓形、字元以及新增影象的方法
       ctx.textBaseline = "bottom";
       //textBaseline = value 基線對齊選項
       //常用值:top, hanging, middle, bottom。

        // 繪製背景顏色
        ctx.fillStyle = this.randomColor(10, 200 );
        //fillStyle = color 設定圖形的填充顏色
        ctx.fillRect(0, 0, this.state.contentWidth, this.state.contentHeight);
        //fillRect(x, y, width, height):繪製一個填充的矩形。 
        
        for (let i = 0; i < this.state.code.length; i++) {
          this.drawText(ctx, this.state.code[i], i);
          //呼叫生成字型顏色和大小及位置函式
        }
       this.drawLine(ctx); //呼叫繪製干擾線函式 如同的線條
      //  this.drawDot(ctx);//呼叫繪製干擾點函式 個人覺得不好看 但是也可以講解一下,後文會在干擾線後面寫
      
      }
    );
  }

設定點選事件

reloadPic = () => {
    this.randomCode();//呼叫生成字母數字組合函式 
    //同時
    this.props.form.setFieldsValue({
      sendcode: "",  //清空輸入框的驗證碼
    });
  };

驗證驗證碼是否正確

//驗證驗證碼是否正確
  changeCode = (e) => {
    //toLowerCase()的意思是把字串所有英文字母轉為小寫
    //對驗證碼進行驗證 
    var code=e.target.value.toLowerCase();
    //得到當前輸入的值
    var v_code=this.state.code.toLowerCase();
    //當前canvas驗證碼的值
    //判斷是否相等,不相等則更新
    if(code!==''&&code!==v_code){
      this.setState({
        showError: true,
      });
    }else{
      this.setState({
        showError: false,
      });
    }
  }

完成!如有不懂的請在在下方留言