使用canvas手写一个前端验证码生成器

使用canvas手写一个前端验证码生成器

一月 08, 2022
该文章更新于 2022.01.08

闲来无事,就想着写一个玩玩,话不多说,先看效果:

image-20220108230119566

image-20220108230150145

image-20220108230202887

image-20220108230214154

image-20220108230229081

上源码:

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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>前端生成验证码</title>
</head>
<body>
<!--画布节点-->
<canvas id="canvas" width="160" height="50"></canvas>
</body>
<script>
// 数字,大写字母,小写字母对应的阿斯克码值
// '0'-'9':48-57
// 'A'-'Z':65-90
// 'a'-'z':97-122

// 获取随机数(随机验证码、canvas随机值都使用到此函数)
const getRandom = (min, max) => {
return Math.floor(Math.random() * (max - min + 1)) + min
}


// 获取随机颜色
const getColor = (min, max) => {
let r = getRandom(min, max);
let g = getRandom(min, max);
let b = getRandom(min, max);
return `rgb(${r},${g},${b}`
}


// 获取验证码,在获取的过程中绘制文字、干扰线、干扰圆点
const getVerificationCode = (selector, width, height) => {
/**
* 这里是定义画布
* **/
// 获取节点元素
let canvas = document.querySelector(selector);
// 获取画布
let ctx = canvas.getContext('2d');
// 绘制背景,先获取背景颜色,再设置绘制的起始坐标,以及绘制的宽高
ctx.fillStyle = getColor(215, 250);
ctx.fillRect(0, 0, width, height);


/**
* 这里是获取验证码,并且绘制到画布
* **/
// 定义一个字符串,保存验证码结果
let verificationCode = '';
// 循环5次,获取五个验证码字符,并且绘制到画布上
for (let i = 0; i < 5; i++) {
// 得到字符的ASCII码值
let ascii = getRandom(48, 122);
// 在这个范围的ascii码是无效的,i--,跳过此次循环
if ((ascii > 57 && ascii < 65) || (ascii > 90 && ascii < 97)) {
i--;
continue;
}
// ascii码有效
// 通过ASCII码值得到相应的字符
const c = String.fromCharCode(ascii);
// 拼接验证码
verificationCode += c;

/**
* 以上部分已经获取到了所有验证码
* 以下的代码是设置文字的渲染样式
*/

// 随机字体大小
let fontSize = getRandom(height-(height*.4), height-(height*.1));
// 设置字体大小和字体类型
ctx.font = fontSize + 'px Simhei';
// 设置文字的基线,这里设置以顶部为基线
ctx.textBaseline = 'top';
// 设置字体的填充颜色
ctx.fillStyle = getColor(80, 150);
// 保存样式
ctx.save();
// 设置文字的位移
ctx.translate(30 * i + 20, 10);
// 随机字体旋转角度
let deg = getRandom(-30, 30);
// 设置文字的旋转角度
ctx.rotate(deg * Math.PI / 180);
// 绘制文字
ctx.fillText(c, -10, -10);
// 恢复,准备绘制下一个文字
ctx.restore();
}


/**
* 这里是绘制干扰线
* **/
// 随机干扰线
for (let j = 0; j < 5; j++) {
// 干扰线起始路径
ctx.beginPath();
// 起点
ctx.moveTo(getRandom(0, width), getRandom(0, height));
// 终点
ctx.lineTo(getRandom(0, width), getRandom(0, height));
// 随机干扰线颜色
ctx.strokeStyle = getColor(180, 230);
// 关闭路线
ctx.closePath();
// 绘制路线
ctx.stroke();
}


/**
* 这里是绘制小圆点
* **/
// 随机干扰圆点
for (let j = 0; j < 40; j++) {
ctx.beginPath();
// 设置圆点的位置,半径,形状
ctx.arc(getRandom(0, width), getRandom(0, height), 1, 0, 2 * Math.PI);
ctx.closePath();
// 设置圆点颜色
ctx.fillStyle = getColor(150, 200);
// 绘制圆点
ctx.fill();
}
// 返回验证码(这里只是一个验证码字符串)
return verificationCode;
}


let verificationCode = getVerificationCode('#canvas', 160, 60);


console.log("生成的验证码是:", verificationCode);
</script>
</html>