拿捏canvas,从实现环形进度条与随机验证码开始

首页 编程分享 JQUERY丨JS丨VUE 正文

睡着学 转载 编程分享 2024-06-11 20:07:16

简介 canvas是HTNL5中才引入的元素。canvas元素为网页提供了可以通过JavaScript完成绘画的画布。可通过编写canvas元素脚本在网页上生成动态图形和复杂的视觉效果。


canvas

canvas是HTML5中才引入的元素。canvas元素为网页提供了可以通过JavaScript完成绘画的画布。可通过编写canvas元素脚本在网页上生成动态图形和复杂的视觉效果。你甚至可以通过对canvas元素编写脚本,在页面上生成蒙娜丽莎。

通过完成环形进度条和随机验证码这两个小案例掌握canvas。

使用步骤

创建画布

canvas是HTML标签。在HTML中,通过<canvas></canvas>创建一个画布,也可以指定特定的高度和宽度。eg:

<canvas id="canvas" width="500" height="500"></canvas>

效果如图:

获取canvas元素

要使JavaScript和html进行交互,就需要通过JavaScript获取html中的元素:

let canvas = document.getElementById('canvas')

通过getContext('2d')获取canvas元素的二维绘图上下文对象:

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

有了这个对象就可以通过使用这个对象的方法和属性进行绘制操作。

绘制

  1. 常用绘制属性:
    • widthheight:控制画布的高度和宽度。
    • fillStyle:控制填充颜色。
    • strokeStyle:控制描边颜色。
    • lineWidth:控制线条的宽度。
  2. 常用绘制方法:
    • fillRect(x, y, width, height):填充矩形。
    • strokeRect(x, y, width, height):绘制矩形的边框。
    • beginPath()closePath():开始和结束一个路径。
    • moveTo(x, y):将当前绘制点移动到指定的坐标 。
    • lineTo(x, y):在当前路径上添加一条从当前点到指定坐标点的直线段。
    • fill():填充路径。
    • stroke():描边路径。
    • arc(x, y, radius, startAngle, endAngle, counterclockwise):绘制圆形,其中(x,y)是圆心,radius是半径,startAngle和endAngle是开始和结束的弧度,counterclockwise是是否逆时针。
    • clearRect(x, y, width, height): 清除指定区域。
    • save()restore():保存和恢复绘图状态栈。

实现动画效果

结合JavaScript的事件监听和定时器实现动画效果。

圆形进度条

html部分

创建一个宽高皆为500px,背景颜色为黑色的canvas画布。

<canvas id="canvas" width="500" height="500" style="background-color: black;"></canvas>

JavaScript部分

初始化变量

let canvas = document.getElementById('canvas'),
    ctx = canvas.getContext('2d'),
    centerX = canvas.width / 2,
    centerY = canvas.height / 2,
    rad = Math.PI * 2 / 100,
    speed = 0.1

  • 获取页面的canvas元素和其2D绘图上下文。
  • 计算画布的中心点。
  • 将360度分成100份作为每次增加的度数。
  • 初始化动画的速度为0.1。

绘制圆环

function drawCircle(n) {
    ctx.save()
    ctx.strokeStyle = '#fff'//设置线条颜色
    ctx.lineWidth = 5//设置线条宽度
    ctx.beginPath()
    ctx.arc(centerX, centerY, 100, -Math.PI / 2, -Math.PI / 2 + n * rad)
    ctx.stroke()
    ctx.closePath()
    ctx.restore()
}
  1. 通过ctx.save()保存当前的Canvas绘图上下文的状态,然后继续绘制操作,再通过ctx.restore()恢复到这个保存的状态。
  2. 通过ctx.beginPath()开始一个新的路径,防止与之前的图形相连。
  3. 通过ctx.arc(centerX, centerY, 100, -Math.PI / 2, -Math.PI / 2 + n * rad)绘制一个圆心为画布中心点,半径为100,起始角度为-Math.PI / 2,结束角度为 -Math.PI / 2 + n * rad的圆弧。
  4. 调用stroke()来绘制线条。
  5. 使用closePath()结束路径。
  6. 使用restore()恢复之前保存的绘图状态。

绘制百分比

function drawNumber(n) {
    ctx.save()
    ctx.strokeStyle = '#fff'//设置描边颜色
    ctx.font = '40px Arial'//设置字体和字体大小
    ctx.strokeText(n.toFixed(0) + '%', centerX - 40, centerY + 10)
    ctx.restore()
}

一样的操作,先保存绘图状态,然后继续绘制操作,再恢复绘图状态。

其中的绘制操作是ctx.strokeText(n.toFixed(0) + '%', centerX - 40, centerY + 10),效果是在圆环中心添加当前的speed值四舍五入到整数,然后加上百分号。

动画循环

(function draw() {
    requestAnimationFrame(draw)
    ctx.clearRect(0, 0, canvas.width, canvas.height)
    drawNumber(speed)
    drawCircle(speed)
    if (speed >= 100) {
        return speed = 100
    }
    speed += 0.1
})()

通过一个立即执行函数开始进行递归操作。

requestAnimationFrame是个用于在页面重绘之前执行特定代码的方法。每次调用requestAnimationFrame 会在下次浏览器重绘之前执行传入的回调函数,从而实现连续、流畅的动画效果。

通过执行 ctx.clearRect(0, 0, canvas.width, canvas.height)在每一帧开始的时候就清除整个画布,进行重新绘制。

调用drawNumber(speed)drawCircle(speed)绘制环形进度条和进度百分比。

speed达到100时停止增加,并且让其重置为100。

在每一帧结束的时候,speed值增加0.1,模拟进度增加的效果。

最终效果

随机验证码

html部分

创建一个宽为120,高为40,并且具有点击事件的画布。在点击画布区域时就会重新生成一个验证码。

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

JavaScript部分

初始化变量

let pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'

定义了一个字符串,其中包含了所有可能用于生成验证码的大写字母和数字。

随机数生成函数

function randomNum(min, max) {
    return Math.floor(Math.random() * (max - min) + min)
}

通过Math.random() * (max - min) + min生成一个在minmax之间的随机数,并且通过Math.floor()对该随机数进行向下取整。

随机颜色生成函数

function randomColor(min, max) {
    const r = randomNum(min, max)
    const g = randomNum(min, max)
    const b = randomNum(min, max)
    return `rgb(${r},${g},${b})`
}

通过调用三次随机数生成函数生成三个随机数作为rgb的三个参数,最后通过生成的三个随机数生成一个随机的颜色并返回。

主函数

function draw() {
    let canvas = document.getElementById("canvas");
    let ctx = canvas.getContext("2d");
    ctx.fillStyle = randomColor(100, 230)
    ctx.fillRect(0, 0, canvas.width, canvas.height)
    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, 150)
        ctx.save() 
        ctx.translate(30 * i + 15, 15)
        ctx.rotate((deg * Math.PI) / 180)
        ctx.fillText(text, -10, -15)
        ctx.restore() 
    }
    //随机生成干扰线段
    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, 2 * Math.PI)
        ctx.fillStyle = randomColor(150, 200)
        ctx.closePath()
        ctx.fill()
    }
}
  1. 首先获取canvas元素,并且获取其2D渲染上下文。
  2. 在100到230的区间内随机生成一个填充颜色作为画布的颜色。
  3. 定义一个imgCode 变量并且赋值为空字符串,为了通过用imgCode拼接验证码字符形成新的字符串。
  4. 通过第一个for循环,循环4遍在画布上生成4个随机的验证码字符,具体的操作如下:
    • 通过生成一个字符串的随机下标实现随机产生一个随机字符,再通过imgCode进行拼接。
    • 为验证码字符设置随机字体大小、随机旋转角度和随机颜色。
    • 通过ctx.translate(30 * i + 15, 15)使每个字符的位置都不同,防止重复重叠;通过ctx.rotate((deg * Math.PI) / 180)使字符具有倾斜角度;最后绘制字符形状。
  5. 通过第二个for循环,循环5遍在画布上生成5个随机的干扰线段。对线段的起点和终点进行随机生成,并且随机生成线段的颜色。
  6. 通过第三个for循环,循环40遍在画布上生成40个随机的干扰点。通过ctx.arc(randomNum(0, canvas.width), randomNum(0, canvas.height), 1, 0, 2 * Math.PI)生成随机位置的半径为1的小圆点,再对小圆点设置随机颜色。

最后效果

转载链接:https://juejin.cn/post/7378014138138886195


Tags:


本篇评论 —— 揽流光,涤眉霜,清露烈酒一口话苍茫。


    声明:参照站内规则,不文明言论将会删除,谢谢合作。


      最新评论




ABOUT ME

Blogger:袅袅牧童 | Arkin

Ido:PHP攻城狮

WeChat:nnmutong

Email:nnmutong@icloud.com

标签云