# 验证码

源码预览 (opens new window) html


<div class="outWrapper">
  <div class="iptWrapper">
    <input type="text" placeholder="请输入验证码" name="code" pattern="[A-z]{3}" autocomplete="off" required title="验证码输入框">
  </div>
  <canvas id="canvas" width="120" height="40" onclick="getValidatorCode('#canvas', 120, 40)"></canvas>
</div>
<div>
  <button class="btn">提交</button>
</div>
<input type="number" min="1" max="20" class="iptNumber">
1
2
3
4
5
6
7
8
9
10
11

css

.outWrapper {
      display: flex;
    }
    #canvas {
      cursor: pointer;
    }
    .iptWrapper {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 120;
      height: 40px;
      border: solid #ccc 1px;
      box-sizing: border-box;
      padding:4px 8px;
      margin-right: 10px;
    }
    .iptWrapper input {
      outline: none;
      border: 0;
      width: 100%;
      height: 38px;
      line-height: 38px;
      box-sizing: border-box;
    }
    /* input::after{
      content: '已勾选';
      width: 100px;
      height: 40px;
      margin-left: 30px;
      display: block;
    } */
    .btn {
      width: 80px;
      height: 40px;
      background-color: skyblue;
      line-height: 40px;
      border-color:skyblue;
      border:0;
      margin-top: 20px;
      cursor: pointer;
    }
    .btn:hover {
      color: #fff;
      background-color: steelblue;
    }
    input.iptNumber {
      margin-top: 20px;
      width: 200px;
      height: 40px;
    }
    input.iptNumber:out-of-range:focus {
      background: red;
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

js




/**
 * @description: 封装的验证码生成函数
 * @param {selector} 画布选择器
 * @param {width} 画布宽
 * @param {height} 画布高
 * @return {*}
 */
let compareCode = '';

const oBtn = document.querySelector('.btn');
const oIpt = document.querySelector('.iptWrapper input');
oBtn.onclick = () => {
  const iptValue = oIpt.value;
  if(!iptValue) return;
  if(iptValue.toLowerCase() === compareCode.toLowerCase()) {
    alert('验证成功')
  } else {
    alert('验证失败,请重新输入!');
    getValidatorCode('#canvas', 120, 40);
  }
  // console.log('iptValue', iptValue);
}
function getValidatorCode(selector, width, height) {

  let resultCode = '';
  // 随机数
  function randomNumber(min, max) {
    return parseInt(Math.random() * (max-min) + min);
  }

  //随机颜色
  function randomColor (min, max) {
    const r = randomNumber(min,max);
    const g = randomNumber(min,max);
    const b = randomNumber(min,max);
    return `rgb(${r},${g},${b})`
  }

    const canvas = document.querySelector(selector);
    const w = width;
    const h = height;
    const ctx = canvas.getContext('2d'); //创建画笔


    // console.log('color', randomColor(180,230));
    ctx.fillStyle = randomColor(180,230);
    ctx.fillRect(0, 0, w,h);

    const pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890';

    for(let i = 0; i<4; i++) {
      //随机验证码数字
      const c = pool[randomNumber(0, pool.length)];

      

      //随机字体大小
      const fs = randomNumber(18,40);

      //随机数字旋转角度
      const deg = randomNumber(-30, 30);

      //字体大小
      ctx.font = fs + 'px Simhei';

      //基线位置
      ctx.textBaseline = 'top';
      //设置字体颜色
      ctx.fillStyle = randomColor(80,150);
      //绘制保存
      ctx.save();

      //移动每个验证码位置
      ctx.translate(30 * i + 15, 15);
      //旋转每个字符
      ctx.rotate(deg * Math.PI/180);

      //填充文字
      ctx.fillText(c, -10, -10);

      //每次填充完再恢复回去
      ctx.restore();

      resultCode +=c;
    }


    //随机生成干扰线
    for(var i = 0; i<5; i++) {
      //起始路径
      ctx.beginPath();
      ctx.moveTo(randomNumber(0, w), randomNumber(0, h));
      ctx.lineTo(randomNumber(0, w), randomNumber(0, h));
      ctx.strokeStyle = randomColor(180, 230);
      ctx.closePath();
      ctx.stroke();
    }

    // 随机产生40个小圆点干扰
    for(var i = 0; i < 40; i++) {
      ctx.beginPath();
      //画圆
      ctx.arc(randomNumber(0, w),randomNumber(0, h),1, 0, 2 * Math.PI);
      ctx.closePath();

      //填充颜色
      ctx.fillStyle = randomColor(150,200);
      ctx.fill(); //填充
    }

    compareCode = resultCode; //用于和外面验证码比较

    return resultCode;

}

getValidatorCode('#canvas', 120, 40);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
最后更新时间: 5/19/2023, 2:54:06 PM