工作总结(7)

这篇工作总结会整理一下使用Canvas实现随机生成验证码。

随机生成验证码是基于canvas绘制而成的,最基本的实现是随机生成多位验证码,然后验证码的每一位码按不同的颜色,大小,倾斜角度跟位置来绘制到画布上。更上一层是增加干扰项,比如划线,非验证码范围字符,验证码扭曲,定时更新验证码等等。这里实现的验证码只是增加了干扰项跟点击更新,定时更新可以实现,但这里就不整理了。

这里的代码实现基于vue实现的。

初始化工作

要实现随机验证码,有两个基本要素:canvas画布,随机生成的验证码(这里演示4位验证码)字符范围。

canvas绘制不难,主要是使用绘制的方法,这个后面整理。先要在页面上获得canvas画布,这一步需要在mounted中执行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- html template -->
<canvas id="verCode"></canvas>

// js
data () {
// ...
}
mounted () {
this.initCanvas();
},
methods: {
initCanvas () {
this.container = document.querySelector('#verCode');
this.width = this.container.width;
this.height = this.container.height;
this.ctx = this.container.getContext('2d');
this.ctx.textBaseline = 'bottom';
},
}

上面通过.getContext('2d')获取了画布,然后在获得画布的宽高,设置了画布的文字基线。

生成code

接下来就是生成code。生成code是比较简单的,思路是从特定的字符集合中随机取出字符组成code。这里把特定的字符放到一个字符串中,然后随机生成数组下标,取出字符串。随机生成的code的长度可以从外部传进来,也可以使用默认的四位:

1
2
3
4
5
6
7
8
9
10
getCode () {
let chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
let code = [];
let radix = chars.length;
for (let i = 0; i < this.num; i++) {
code[i] = chars[0 | Math.random() * radix];
}
this.code = code.join('');
console.log(this.code);
},

画code

生成code之后,就可以开始在canvas画布上画code了。这里用到的是canvas的fillText()方法,这个方法可以把文字绘画到canvas上。在调用fillText()方法之前,还可以给文字增加属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
drawCode () {
for (let i = 0; i < this.num; i++) {
let x = (this.width - 20) / this.num * i + 15;
let y = this.randomNum(this.height * 0.92, this.height * 0.92);
let deg = this.randomNum(-45, 45);
let txt = this.code.charAt(i);

this.ctx.fillStyle = this.randomColor(10, 100);
this.ctx.font = `${this.randomNum(80, 100)}px SimHei`;
this.ctx.translate(x, y);
this.ctx.rotate(deg * Math.PI / 180);
this.ctx.fillText(txt, 0, 0);
this.ctx.rotate(-deg * Math.PI / 180);
this.ctx.translate(-x, -y);
}
},

干扰项

干扰项一般增加直线跟曲线就可以了,如果想要更复杂,也是可以增加符号干扰的,不过要注意控制样式,否则真的会干扰到用户的判断。

这里我爸直线跟曲线的绘画分成两个方法来调用了。绘制的数量我都按code的长度来控制。然后在一定范围内随机生成长度,位置坐标,颜色等。最后调用canvas绘制路线的方法绘制即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
drawLine () {
for (let i = 0; i < this.num; i++) {
this.ctx.strokeStyle = this.randomColor(90, 180);
this.ctx.beginPath();
this.ctx.moveTo(this.randomNum(0, this.width), this.randomNum(0, this.height));
this.ctx.lineTo(this.randomNum(0, this.width), this.randomNum(0, this.height));
this.ctx.stroke();
}
},
drawArc () {
for (let i = 0; i < this.num; i++) {
this.ctx.fillStyle = this.randomColor(0, 255);
this.ctx.beginPath();
this.ctx.arc(this.randomNum(0, this.width), this.randomNum(0, this.height), 1, 0, 2 * Math.PI);
this.ctx.fill();
}
},

点击刷新验证码及验证

点击刷新验证码实现很简单,给canvas增加一个点击监听事件,点击之后调用getCode()方法就可以完成刷新。

验证验证码的实现是先实现一个验证方法,然后在父组件使用验证码组件是使用this.$refs来调用验证码组件的验证方法,传入用户输入的code进行比对,然后返回一个布尔值。

以上就是验证码组件的实现。