likes
comments
collection
share

使用Canvas创建动态验证码<canvas>是HTML5中新增的一个元素,这个元素本身仅仅只是一个容器,真正的绘图工作

作者站长头像
站长
· 阅读数 17

前言

<canvas>是HTML5中新增的一个元素,这个元素本身仅仅只是一个容器,真正的绘图工作是需要通过 JavaScript 的 Canvas API 来完成的。Canvas API 提供的一系列方法和属性使得<canvas>非常适合于绘制动态图形、进行游戏开发、实现复杂的用户界面交互等场景。

本篇文章首先会向读者介绍一些canvas的基础知识,然后通过实操写一个验证码的demo来展示canvas的强大用法。

canvas标签基础

创建了一个HTML文件,向body中添加一个<canvas>元素,并为其设置一个id:canvas(<canvas id="canvas"></canvas>),以便我们可以通过JavaScript来访问它。接着,在<script>标签内,我将编写一些JavaScript代码来绘制图形,以便更加形象地向你们介绍有关canvas的一些方法以及如何使用它们。

首先,我们通过document.getElementById获取canvas元素,并调用其getContext("2d")方法来获取一个2D渲染上下文(即绘图环境)。

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");  //  用canvas标签创建一张2D的画布ctx 

绘制矩形

  • fillRect(x, y, width, height):用于在给定的矩形区域内填充颜色。x 和 y 参数指定了矩形左上角的坐标,width 和 height 参数指定了矩形的宽度和高度。

  • strokeStyle:这是一个属性,它设置了线条或者边框等的描边颜色。

  • strokeRect(x, y, width, height): 类似于 fillRect,但这个方法不是填充矩形,而是用于描边矩形,它同样接受矩形的左上角坐标、宽度和高度作为参数。

ctx.fillRect(0, 0, 100, 100)    // 在画布上绘制一个矩形(两个坐标确定矩形的左上角和右下角)
ctx.strokeStyle = "red"         // 设置描边颜色
ctx.strokeRect(0, 0, 100, 100)  // 描边

绘制圆形

  • beginPath():在进行路径绘制之前调用此方法。它重置当前的路径,清除之前定义的所有点、线和形状,从而开始一个新的路径。

  • closePath():闭合当前路径。从当前点绘制一条直线到路径的起始点,从而闭合路径。closePath() 本身并不绘制任何内容到画布上,它仅仅是定义了一个闭合的路径,该路径可以通过 fill() 或 stroke() 方法来填充或描边。

  • arc(x, y, radius, startAngle, endAngle, anticlockwise):这个方法用于在画布上绘制一个圆或圆弧。x 和 y 定义了圆心的坐标,radius 是圆的半径,startAngle 和 endAngle 是圆弧的起始和结束角度(以弧度为单位),anticlockwise 是一个布尔值,圆弧是否应该按逆时针方向绘制,默认为false,即顺时针方向。

  • fillStyle:用于设置填充样式的属性。

  • fill():使用当前的填充样式(由 fillStyle 属性设置)填充当前的闭合的路径。

ctx.beginPath()                       // 开始一条路径的描述
ctx.arc(150, 75, 50, 0, Math.PI * 2)  // 绘制一个弧形(圆心坐标, 半径, 起始弧度, 结束弧度)
ctx.fillStyle = "blue"
ctx.fill()                            // 填充

绘制空心圆

  • lineWidth:设置描边线条宽度的属性。

  • stroke():遍历当前路径中的所有点,并使用指定的样式来绘制这些点之间的线条。

ctx.beginPath()
ctx.arc(150, 75, 50, 0, Math.PI * 2)
ctx.strokeStyle = "blue"
ctx.lineWidth = 5   // 设置线条的宽
ctx.stroke()        // 描边

创建验证码

HTML结构

在body中定义一个ID为"canvas"的<canvas>元素。设定画布的尺寸为120x40像素,并且包含一个onclick事件监听器,每当点击画布时都会触发draw()函数来绘制新的验证码。

<canvas id="canvas" width="120" height="40" onclick="draw()"></canvas>

JavaScript实现

随机函数

在生成验证码之前,我们需要写一些辅助函数用于生成验证码中的随机文本、颜色、偏转角度、位置等等。因此我们定义了两个函数:randomNum用于生成给定范围内的随机数。randomColor根据给定的最小和最大亮度值生成随机 RGB 颜色。

let pool = "1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

// 随机数
function randomNum(min,max){
    // Math.random()  0-1
    // Math.floor()  向下取整
    return Math.floor(Math.random() * (max - min) + min)
}

// 随机填充色
function randomColor(min,max){
    const r = randomNum(min,max)
    const g = randomNum(min,max)
    const b = randomNum(min,max)
    return `rgb(${r},${g},${b})`
}

绘制验证码

在 draw 函数中,我们利用 Canvas 2D 上下文来绘制验证码。首先,使用随机颜色来填充画布背景,然后循环生成随机字符,再次使用随机函数来设置字体大小、旋转角度等样式。

其中重点介绍一下save 和 restore 方法,它们分别用于保存和恢复当前的绘图状态,这样在绘制下一个字符时不会受到前一个字符的变换(如平移和旋转)的影响。

// 绘制一个验证码
function draw(){
    let canvas = document.getElementById("canvas");
    let ctx = canvas.getContext
    
    // 随机填充色
    ctx.fillStyle = randomColor(180,230)
    ctx.fillRect(0, 0, canvas.width, canvas.
    let imgCode = ''
    
    // 随机生成字符串
    for(let i = 0; i < 4; i++){
        const text = pool[randomNum(0, pool.length)]
        imgCode += text
        // 随机字体大小
        const fontSize = randomNum(18, 40)
        // 随机旋转角度
        const deg = randomNum(-30, 30)
        
        // 绘制文字样式
        ctx.font = `${fontSize}px SimHei`
        ctx.textBaseline = 'top'    // 文字垂直对齐方式
        ctx.fillStyle = randomColor(80, 160)
        ctx.save() // 将当前状态封存入栈
        ctx.translate(i * 30 + 15, 15)
        ctx.rotate((deg * Math.PI) / 180)
        ctx.fillText(text, -10, -15)
        ctx.restore()   // 出栈
     }
}
draw()

添加图形干扰

为了提高验证码的安全性,我们需要添加一些图形干扰,如随机线条和圆点,这些干扰项能够增加机器识别验证码的难度。

// 随机生成干扰线
for(let i = 0; i < 5; i++){
    ctx.beginPath() // 开始一条路径的描述
    ctx.moveTo(randomNum(0, canvas.width), randomNum(0, canvas.height)) // 下笔
    ctx.lineTo(randomNum(0, canvas.width), randomNum(0, canvas.height)) // 移动
    ctx.strokeStyle = randomColor(100, 230)
    ctx.closePath() // 没有会使上次生成的线条粘连在一起
    ctx.stroke()
}
// 随机小圆点
for(let i = 0; i < 40; i++){
    ctx.beginPath()
    ctx.arc(randomNum(0, canvas.width), randomNum(0, canvas.height), 1, 0, Math.PI * 2)
    ctx.fillStyle = randomColor(100, 230)
    ctx.closePath()
    ctx.fill()
}

总结

通过上述步骤,我们成功创建了一个包含随机字符、随机样式以及图形干扰的验证码,用户可以通过点击画布刷新验证码,提高了用户体验。通过本文的介绍,相信你已经对<canvas>元素有了初步的认识,并感受到了它强大的绘图能力。但要知道,这只是Canvas的冰山一角,在不断深入学习canvas后你将能够开发出更加丰富、动态和吸引人的网页内容,为用户带来前所未有的体验。

转载自:https://juejin.cn/post/7389069052437020712
评论
请登录