14 canvas
11 canvas
canvas
canvas 是 HTML5 中的一个元素,用于在网页上绘制图形和动画。它提供了一个矩形区域,你可以使用 JavaScript 在这个区域内绘制各种图形,包括线条、形状、文本、图像等。canvas 元素本身没有绘图能力,所有的绘图操作都需要通过 JavaScript 来完成。
基本用法
- HTML 部分
在 HTML 中添加一个canvas元素,并为其指定一个id,以便在 JavaScript 中引用:1
<canvas id="myCanvas" width="200" height="100"></canvas>
width和height属性定义了canvas的尺寸。如果省略这些属性,canvas的默认尺寸是 300x150 像素。
- JavaScript 部分
使用 JavaScript 获取canvas元素,并获取其绘图上下文(通常是 2D 上下文),然后进行绘图操作:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15const canvas = document.getElementById('myCanvas');
const ctx = canvas.getContext('2d');
// 绘制一个矩形
ctx.fillStyle = 'green'; // 设置填充颜色
ctx.fillRect(10, 10, 150, 100); // 绘制一个填充的矩形
// 绘制一条线
ctx.strokeStyle = 'blue'; // 设置线条颜色
ctx.beginPath(); // 开始一条路径
ctx.moveTo(50, 50); // 移动到起点
ctx.lineTo(150, 50); // 绘制到终点
ctx.stroke(); // 绘制路径
// 绘制文本
ctx.font = '20px Arial'; // 设置字体样式
ctx.fillStyle = 'red'; // 设置文本颜色
ctx.fillText('Hello, Canvas!', 50, 80); // 绘制文本
常用方法和属性
- 绘图上下文:
getContext('2d')返回一个 2D 渲染上下文对象,用于在canvas上进行绘图。 - 绘制形状:
fillRect(x, y, width, height):绘制一个填充的矩形。strokeRect(x, y, width, height):绘制一个矩形边框。beginPath():开始一条新的路径。moveTo(x, y):移动到指定的点。lineTo(x, y):绘制一条线到指定的点。arc(x, y, radius, startAngle, endAngle, anticlockwise):绘制一个圆弧。
- 绘制文本:
fillText(text, x, y):绘制填充文本。strokeText(text, x, y):绘制文本边框。
- 样式和颜色:
fillStyle:设置填充颜色或渐变。strokeStyle:设置线条颜色或渐变。
- 图像操作:
drawImage(image, dx, dy):在指定位置绘制图像。
- 保存和恢复状态:
save():保存当前的绘图状态。restore():恢复之前保存的绘图状态。
应用场景
- 动画:通过不断清除和重绘
canvas来创建动画效果。 - 游戏开发:用于绘制游戏界面和动画。
- 图表和数据可视化:绘制各种图表和图形以展示数据。
- 图像处理:进行图像的裁剪、缩放、滤镜等操作。
canvas提供了强大的绘图功能,使得在网页上进行复杂的图形绘制和动画制作成为可能。
前端截图
前端实现截图需要使⽤ HTML5 的 Canvas 和相关 API,具体步骤如下:
- ⾸先在页面中创建⼀个 Canvas 元素,并设置其宽⾼和样式。
- 使⽤ Canvas API 在 Canvas 上绘制需要截图的内容,⽐如⻚⾯的某个区域、某个元素、图⽚等。
- 调⽤ Canvas API 中的 toDataURL () ⽅法将 Canvas 转化为 base64 编码的图⽚数据。
- 将 base64 编码的图⽚数据传递给后端进⾏处理或者直接在前端进⾏显⽰。
以下是⼀个简单的例⼦,实现了对整个⻚⾯的截图:
1 | const canvas = document.getElementById('canvas'); |
这个例⼦中,在⻚⾯中创建了⼀个 canvas 元素,并设置其宽⾼和样式,将其放在⻚⾯最上⽅。在
点击“截图”按钮时,通过 toDataURL () ⽅法将整个⻚⾯的截图转换为 base64 编码的图⽚数据,
并打印到控制台上。
简单动画
下面是一个简单的 canvas 动画示例,它会在 canvas 上绘制一个不断移动的小球,实现一个简单的动画效果。
HTML 部分
1 |
|
JavaScript 部分 (animation.js)
1 | const canvas = document.getElementById('myCanvas'); |
动画解释
- 初始化:定义了小球的初始位置
x和y,以及水平和垂直方向的速度dx和dy。还定义了小球的半径ballRadius。 - 绘制小球:
drawBall函数使用arc方法绘制一个圆形的小球,并用fill方法填充颜色。 - 动画循环:
draw函数首先清除canvas上的内容,然后调用drawBall绘制小球。接着更新小球的位置,并检查小球是否碰到canvas的边界。如果碰到边界,则反转速度,实现反弹效果。最后,使用requestAnimationFrame(draw)来请求浏览器在下一次重绘之前调用draw函数,从而实现动画效果。 - 启动动画:在脚本的最后调用
draw函数来启动动画。
这个简单的示例展示了如何使用canvas和 JavaScript 创建一个基本的动画效果。你可以根据需要调整速度、颜色、形状等属性来创建更复杂的动画。
requestAnimationFrame
requestAnimationFrame 是 Web API 中的一个函数,用于在浏览器的下一次重绘之前执行动画函数。它提供了一种更高效的方式来创建平滑的动画效果,相比传统的 setTimeout 或 setInterval 方法,requestAnimationFrame 有以下优点:
优点
- 性能优化:
requestAnimationFrame会在浏览器完成一次屏幕重绘之前执行动画函数,通常与浏览器的刷新率(通常是 60 次/秒)同步。这意味着它可以更高效地利用浏览器的重绘机制,避免不必要的渲染,从而提高性能,减少卡顿和撕裂现象。 - 节能:当浏览器标签页不是处于活动状态时(例如用户切换到其他标签页),
requestAnimationFrame会暂停执行动画函数,从而节省资源和电量。 - 更平滑的动画:由于与浏览器的重绘同步,
requestAnimationFrame可以创建更平滑的动画效果,避免出现抖动或不连贯的情况。
使用方法
1 | function animate() { |
参数
callback:一个函数,它会在浏览器下一次重绘之前被调用。这个函数通常包含动画的更新和渲染逻辑。
返回值
- 返回一个
ID值,可以用于cancelAnimationFrame函数来取消动画请求。
取消动画
如果你需要在某些情况下停止动画,可以使用 cancelAnimationFrame 函数:
1 | let animationId; |
requestAnimationFrame 和 setInterval
requestAnimationFrame 和 setInterval 都可以用来创建动画或定时执行代码,但它们在实现方式和性能表现上有一些关键区别:
requestAnimationFrame
- 同步浏览器刷新率:
requestAnimationFrame会在浏览器的下一次重绘之前执行回调函数,通常与浏览器的刷新率(通常是 60 次/秒)同步。这意味着它可以在每次屏幕刷新时更新动画,从而创建平滑的动画效果。 - 性能优化:当浏览器标签页不是处于活动状态时(例如用户切换到其他标签页),
requestAnimationFrame会暂停执行回调函数,从而节省资源和电量。 - 更平滑的动画:由于与浏览器的重绘同步,
requestAnimationFrame可以创建更平滑的动画效果,避免出现抖动或不连贯的情况。 - 适用于动画:特别适合用于创建动画效果,因为它可以确保动画的更新与屏幕刷新同步,减少不必要的渲染,提高性能。
setInterval
- 固定时间间隔:
setInterval会按照指定的时间间隔(以毫秒为单位)重复执行回调函数,不考虑浏览器的刷新率。这意味着它可能会在浏览器的两次重绘之间执行多次,或者在浏览器的两次重绘之间不执行,导致动画效果不平滑。 - 资源消耗:即使浏览器标签页不是处于活动状态,
setInterval仍然会继续执行回调函数,可能会消耗不必要的资源和电量。 - 不考虑重绘:
setInterval不会自动与浏览器的重绘同步,可能导致动画的更新与屏幕刷新不同步,出现抖动或不连贯的情况。 - 适用于定时任务:更适合用于需要在固定时间间隔执行的定时任务,而不是动画效果。
总结
- 动画效果:对于创建动画效果,
requestAnimationFrame是更好的选择,因为它可以与浏览器的重绘同步,创建平滑的动画,并且在非活动标签页时暂停执行,节省资源。 - 定时任务:对于需要在固定时间间隔执行的定时任务,
setInterval可以满足需求,但需要注意它可能会导致动画效果不平滑,并且在非活动标签页时仍然消耗资源。
通过理解requestAnimationFrame和setInterval的区别,可以根据具体需求选择合适的函数来实现动画或定时任务。