手把手写个Canvas验证码组件,并且与Vue解耦

今天上班摸鱼,咱们一起来写一个利用canvas画布纯前端实现验证码功能。
开始之前我们先撸一撸开发的流程,先干什么再干什么,把思路撸清楚了,干什么都容易。

  1. 当然必须先有一个canvas画布
  2. 接着再整几个数字+英文上去

screenshot-20220815-112115.png

我们先来个空标签,先占个位,以后这里就会有一个canvas。

<span id="verify"></span>

并且我们定义了一个id为verify。
接下开始整canavs了,我们需要把canvas变到span里面。
没有canvas,就创建一个。

const node = document.getElementById('verify')
const canvas = document.createElement('canvas');
node.appendChild(canvas)
canvas.width = 120
canvas.height = 60

并且我们顺手把它塞进了span里面。到这里我们的小目标第一步已经完成了。接下去再整几个数字+英文上去就完事了。
要在canvas上整点东西,当然先要拿到canvas。

const ctx = canvas.getContext('2d');

然后我们直接进入小目标的第二步。

ctx.fillText('jsx123', 0, 0);

到这里估计有人要喷我了,你TM整的什么玩意儿。
验证码怎么是写死的,不应该是随机的吗。
是的,没错。
下面我们就来实现小目标中的细节。
我们需要得到一个随机的数字+字母组合,字母大小写也是随机的。
先定义一段字符串。

const str = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789'

到这里我们只需要随机选取字符串中的字符即可。我们封装一个方法,来返回指定长度的随机字符串。

function getString(length) {
  let str = 'abacdefghjklmnopqrstuvwxyzABCDEFGHJKLMNOPQRSTUVWXYZ0123456789'
  let string = ''
  for (let i = 0; i < length; i++) {
    string += str[Math.floor(Math.random() * str.length)]
  }
  return string
}

image.png
控制台跑一下,是我们想要的结果,改一下我们的代码。

ctx.fillText(getString(6), 0, 0);

这样我们每次刷新,出现的验证码都是随机的。
但是验证码的颜色不是随机的,而且验证码排列的方式也不是我们想要的。
我们希望验证码的每个字符的颜色都是随机的,而且每个字符需要带点旋转,以提高机器识别的难度。

// 生成随机色
 function randomColor() {
    return `#${((Math.random() * (0xFFFFFF).toString(10)).toString(16)).slice(-6)}`
  }

不知道怎么随机生成16进制颜色的,可以直接百度。或者使用随机获取0-255整数的方法获得rgb颜色。
这里我们需要遍历验证码的每一个字符。

// 生成指定范围内的随机数
function getRandom(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min
}

let code = getString(6)
for (let i = 0; i < code.length; i++) {
    ctx.save()
    ctx.strokeStyle = randomColor()
    ctx.rotate(getRandom(-30, 30) * Math.PI / 180)
    ctx.fillText(code[i], 0, 0);
    ctx.restore()
}

到这一步我们一次性完成了验证码字符的颜色随机和角度旋转。
为了干扰机器识别,我们需要添加杂线。

ctx.lineWidth = getRandom(1, 3)
ctx.strokeStyle = randomColor()
ctx.beginPath();
ctx.moveTo(start, end);
ctx.lineTo(start, end);
ctx.stroke();

这里我们还是需要使用for循环依次画出多条杂线,可以看到lineWidth以及strokeStyle线宽度和填充色都使用了随机值,特别注意的是线的起点和终点start,end,依旧传入随机值。比如:

const start = getRandom(-width / 2, width * 1.5)
const end = getRandom(-height / 2, height * 1.5)

到这里一个字符随机,字符颜色随机,字符角度随机,背景杂线随机的验证码已经完成了。

screenshot-20220815-112115.png
在一些细节中我们可以做出相应的改变,如此一来验证码的功能将不断完善,比如背景可以使用不同透明度的随机色字符作为干扰,或者是弧线,或者是虚线。
同时验证码还可以做加减乘的计算,我们只需要随机取2个数字和1个运算符号,将他们画在canvas上。

由于篇幅的问题,具体的实现流程不在这里阐述了,详细的代码我已上传github。

https://github.com/humanlegacy/canvas-verify-code

或者npm安装查看源码

# 安装依赖
npm i canvas-verify-code

文章写完了,我该溜了溜了,不足之处大家评论区留言讨论呀

48 声望
2 粉丝
0 条评论
推荐阅读
原来 Canvas 也能直接绘制圆角矩形了
很多时候,在使用 Canvas 绘制圆角矩形都是一件比较麻烦的事,因为之前并没有直接的方法,只能通过直线和圆弧间接组合而成,下面是一个常规绘制方式

XboxYan6阅读 2.2k

封面图
three.js简明教程之:【1】入门用例
和直接使用WebGL相比,比如 着色器 ,大部分情况下你无需自己开发,不过,情况并不总是这样,如果你的需求太过特殊,我们依旧可以用更接近原生的方式来绘制,这是一个非常友好的设计。

zxl200707012阅读 590

封面图
CSS、SVG、Canvas对特殊字体的绘制与导出
欢迎关注我的公众号:前端侦探最近在项目中需要对特殊字体进行绘制与导出,如下简单解释一下:所谓绘制,就是视觉上可以看到就行(预览状态),导出呢,就是将看到的转换成图片(或者Canvas),以便于后续处理。...

XboxYan3阅读 981

封面图
WebGL简明教程之:【2】使用缓冲区绘制三角形
纯色三角形我们首先借助缓冲区绘制一个三角形:完整的代码如下: {代码...} 接着,我们将来解读上面这段代码。着色器三角形一共有3个点,因此不能再写死了,需要定义变量使用缓冲区进行传递,顶点着色器修改如下...

zxl200707011阅读 905

Canvas鼠标滚轮缩放以及画布拖动(图文并茂版)
Canvas鼠标滚轮缩放以及画布拖动本文会带大家认识Canvas中常用的坐标变换方法 translate 和 scale,并结合这两个方法,实现鼠标滚轮缩放以及画布拖动功能。&lt;div align=center&gt; {代码...} &lt;/div&gt;Canva...

astonishqft2阅读 338

封面图
【音视频】YUV
和 RGB 表示图像类似,每个像素点都包含 Y、U、V 分量。但是它的 Y 和 UV 分量是可以分离的,如果没有 UV 分量一样可以显示完整的图像,只不过是黑白的,所以yuv图像可以兼容於黑白影像和彩色影像。

看见了阅读 1.3k

canvas 涂鸦画板,支持笔写、手写、鼠标绘图
已知问题: 笔写需要移动端的触屏笔才能触发,基于pointerType判断,可能存在笔或系统被改过部分浏览器无法识别为笔,从而笔触发pointerType还是touch类型。

tomiaa2阅读 378评论 1

封面图
48 声望
2 粉丝
宣传栏