引言
你有时候是不是觉得验证码的效果看起高大上,过于复杂的?这样的页面效果是不是需要花费很多功夫才能完成,其实通过本章的学习就会发现不过尔尔,这只是一个简单的页面布局罢了,展示一下效果:
不断地点击一样可以一直更换。
Convas
JavaScript中的Canvas功能强大且多样化,它不仅限于基础的图形绘制,还涵盖了图像处理、动画创建以及高级交互性功能。以下是Canvas的一些核心功能:
-
图形绘制:
- 支持绘制点、线、圆形、矩形、椭圆、弧线等多种基本图形。
- 可以设置线条的粗细、颜色、线帽样式、虚线模式等。
- 支持填充图形,包括纯色填充、渐变填充、图案填充等。
-
图像处理:
- 能够加载并绘制外部图片到Canvas上。
- 支持图像的缩放、裁剪、旋转等操作。
- 可以操作像素数据,实现滤镜效果,如灰度、模糊、锐化等。
-
文本渲染:
- 支持在Canvas上绘制文本,包括设置字体、大小、颜色和对齐方式。
- 可以测量文本宽度,以便精确布局。
-
路径操作:
- 强大的路径功能,可以创建和操作复杂路径,包括贝塞尔曲线等。
- 支持闭合路径,以及路径的填充和描边。
-
变换操作:
- 提供了平移、缩放、旋转和倾斜等变换功能,可以组合使用,实现复杂变换效果。
-
复合操作:
- 支持全局Alpha设置,即整体透明度控制。
- 可以设置剪切路径,控制绘制区域。
-
动画与交互:
- 利用
requestAnimationFrame
可以创建流畅的动画效果。 - 通过监听鼠标和键盘事件,实现与用户的交互,如拖拽、缩放等。
- 利用
-
数据可视化:
- 适用于创建图表、仪表盘等数据可视化内容,结合JavaScript的数据处理能力,可以灵活展示各种数据。
-
导出图像:
- 可以将Canvas上的内容导出为图片(如PNG、JPEG格式),或者转换成SVG格式,便于保存或分享。
-
集成库支持:
- 有许多强大的JavaScript库(如Fabric.js、Konva.js、EaselJS、Paper.js等)建立在Canvas之上,提供了更高级的抽象层和便利的API,简化复杂图形和动画的创建过程。
通过这些功能,Canvas成为Web开发中实现创意视觉效果和动态用户界面的重要工具。以下我主要讲解三个实例来运用这些功能:
1. 圆形的绘画
canvas最基本的步骤:
let canvas = document.getElementById("canvas")
let ctx = canvas.getContext("2d")
-
获取canvas这个点击事件
-
获取nvas元素的2D渲染上下文,
'2d'
指代二维绘图上下文。 -
填充矩形:
ctx.fillRect(0,0,100,100)
这行代码在canvas上绘制了一个填充的矩形。fillRect(x, y, width, height)
方法接受四个参数,分别代表矩形的左上角坐标(x, y)
以及矩形的宽度和高度。在这个例子中,矩形的左上角位于(0, 0)
,宽高都是100px
,默认使用的是上下文的当前填充色(如果未指定,默认是黑色)。 -
设置描边颜色:
ctx.strokeStyle = 'red'
这行代码设置了接下来要绘制图形的描边颜色为红色。strokeStyle
属性控制了所有后续描边操作的颜色。 -
描边矩形:
ctx.strokeRect(0,0,100,100)
最后这行代码在同样的位置(0, 0)
绘制了一个宽度和高度都为100px
的矩形的边框,颜色为之前设置的红色。strokeRect()
方法只绘制边框,不填充内部。
效果是在canvas上首先绘制了一个100x100像素的填充矩形,然后在同一位置绘制了一个相同尺寸但只有边框的红色矩形,形成了一个带有红色边框的正方形。
ctx.fillRect(0,0,100,100)
ctx.strokeStyle = 'red' //
ctx.strokeRect(0,0,100,100) // 描边
达到预期的效果。
再画一个圆形并且填充颜色:
ctx.beginPath() //多边形的描绘,开始一个路径的描述
ctx.arc(150,75,50,0,2 * Math.PI)
ctx.fillStyle = 'green'
ctx.fill()
-
开始路径:
ctx.beginPath()
这行代码表示开始一个新的路径描述。在Canvas中,当你想要绘制独立的形状时(避免它们自动连接),通常会在绘制前调用此方法。这样可以确保新图形的起点不会与前一个图形的终点相连。 -
绘制圆形:
ctx.arc(150, 75, 50, 0, 2 * Math.PI)
这行代码用于绘制一个圆形。arc(x, y, radius, startAngle, endAngle)
方法用于创建弧线(用于圆形、部分圆等)。在这个例子中:x
和y
分别是圆心的坐标,即(150, 75)
。radius
是圆的半径,这里是50
像素。startAngle
和endAngle
定义了圆弧的起始和结束位置,以弧度为单位。0
表示从三点钟方向开始,而2 * Math.PI
表示完整一圈,因此会绘制一个完整的圆。
-
设置填充颜色:
ctx.fillStyle = 'green'
这行代码设置了即将填充图形的颜色为绿色。 -
填充图形:
ctx.fill()
调用fill()
方法后,根据之前设置的填充颜色(这里是绿色),填充当前路径描述的内部区域,即刚刚定义的圆形。
到这里想一想镂空的圆形该怎么形成?
ctx.beginPath()
ctx.arc(150,75,50,0,2 * Math.PI)
ctx.strokeStyle = 'blue'
ctx.lineWidth = 6
ctx.stroke()
只要注意下格式的更改,绘制圆形的轮廓和宽度即可。
2. 圆形倒计时:
这里主要可以分为三个部分:绘制圆环,数值的确定,以及绘画的运行。
- 圆环的制定:
function blueCircle(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()
}
这里注意一下有Begin的开始,就添加一个Close的结束这样整体的效果会更好。
- 计算数值:
function text(n) {
ctx.save() //
ctx.strokeStyle = '#fff'
ctx.font = '40px Arial'
ctx.strokeText(n.toFixed(0) + '%',centerX - 25,centerY + 10)
// ctx.stroke()
ctx.restore() // 跟save一样
}
这保证接下来的样式只生效于这一段。
- Draw的绘画
(function draw() {
requestAnimationFrame(draw)
ctx.clearRect(0, 0, canvas.width, canvas.height)
text(speed)
blueCircle(speed)
if (speed >= 100) {
speed = 100
}
speed += 0.1
})()
这里的定时器除了基本的两种:setTimeout() 和 setTimeout(),还可以使用requestAnimationFrame()来执行。
基本的效果可以达成:
3. 验证码
其实验证码的写法也是类似,这里就不多叙述了,大家可以看看源码更正一下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<canvas id="canvas" width="120" height="40" onclick="draw()"></canvas>
<script>
let pool = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890'
function randomNum(min, max) {
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})`
}
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(120,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()
}
}
draw()
</script>
</body>
</html>
基本的效果就是最开始的情况。
总结:
其实Convas的编写远不止于此,任何(evey)的效果美化,只要你想并且去写,就能够跑起来,甚至居左《蒙娜丽莎》也是可以的!