【HTML】Canvas 基本介绍与应用
- 前言
- 一、Canvas 概述
- 二、在 HTML 中使用 Canvas
- 三、Canvas 绘制图形
- 1、绘制矩形
- a. fillRect()
- b. strokeRect()
- 2、绘制圆形
- a. 绘制实心圆形
- b. 绘制空心圆形
- 四、Canvas 绘制文本
- 1、 fillText()
- 2、 strokeText()
- 五、Canvas 绘制图片
- 1、drawImage()
- 2、createPattern()
- 六、Canvas 动画效果
- 1、setInterval() 实现动画
- 2、requestAnimationFrame() 实现动画
- 七、Canvas 使用注意事项
- 八、利用Canvas绘制挂钟(原理-绘制弧形)- 简单练习
- 1、 还原坐标系
- 2、 绘制背景
- 3、 绘制时钟指针
- 4、循环绘制
- 5、最后的效果:(视频我就不展示了,下边有源码,你们可以自己试试)
- 6、总结
- 7、完整代码如下,其中注释中有更详细的解释:
- 总结
前言
Canvas
是 Web 开发中一个重要的绘图工具,其最大的优势在于:支持动态绘制和动画效果,且对 CPU 资源使用较少,可以实现日常开发中的非常多的想象和需求。本文将会讲解 Canvas
的相关知识,包括它的基本概念、如何应用以及使用注意事项等。
一、Canvas 概述
Canvas
是一种使用JavaScript
在网页上绘制图像的HTML
标签,它提供了一组 API,可以绘制2D
和3D
两种图形。- Canvas 可以画出各种图形,包括
点、线、圆、弧、多边形等
,也可以显示文本、图片
等。 - Canvas API 很强大且易于使用,可以绘制
动画、图表、游戏和其他效果
,这些效果可以拥有不同的交互和开发自定义的功能。
二、在 HTML 中使用 Canvas
在 HTML 中添加 Canvas,只需要添加一个 <canvas>
标签即可。该标签需要设置宽度(width)和高度(height)属性。如下所示:
<canvas id="canvas" width="400" height="200"></canvas>
在 JavaScript 中,获取 Canvas 对象并在 Canvas 中绘制图形。代码如下:
//获取canvas节点
const canvas = document.getElementById('canvas');
//获取上下文,取2d
const ctx = canvas.getContext('2d');
//绘制矩形
ctx.fillRect(50, 50, 100, 100);
//绘制圆形
ctx.beginPath();
ctx.arc(200, 100, 50, 0, Math.PI * 2, false);
ctx.closePath();
ctx.fill();
三、Canvas 绘制图形
Canvas 目前支持的图形主要包括:矩形、圆、弧、线段、文本和图片等
,这里只简单介绍矩形和圆。
1、绘制矩形
Canvas 绘制矩形主要用到了 fillRect()
和 strokeRect()
方法。图形绘制原理如下图所示:
a. fillRect()
fillRect(x, y, width, height)
方法用于绘制填充矩形,其中 x
和 y
表示左上角坐标,width
和 height
分别表示矩形的宽和高。示例代码如下:
ctx.fillRect(50, 50, 100, 100);
b. strokeRect()
strokeRect(x, y, width, height)
方法用于绘制描边矩形,可以为描边设置样式。示例代码如下:
ctx.strokeStyle = '#FF0000';
ctx.strokeRect(50, 50, 100, 100);
2、绘制圆形
Canvas 绘制圆形需要使用到 arc()
和 stroke()
方法。其中,arc()
方法需要设置圆心坐标、半径、起始弧度和终止弧度。起始弧度和终止弧度是以弧度为单位,通常指定为 0
和 2× π
,起始弧度必须大于终止弧度,否则图形会出现问题。绘制圆形的原理如下图所示:
a. 绘制实心圆形
fill()
方法用于填充整个路径区域,示例代码如下:
//绘制实心圆形
ctx.beginPath();
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.fillStyle = "red";
ctx.fill();
在这个例子中,arc()
方法用于画圆,分别传入圆心的 x 坐标、y 坐标、圆的半径、起始弧度和终止弧度(这里指绘制整个圆形的起始弧度和终止弧度),使用 fillStyle
设置填充颜色,最后使用 fill()
方法填充整个路径区域。
b. 绘制空心圆形
stroke()
方法用于描边路径,示例代码如下:
ctx.beginPath();
ctx.arc(100, 100, 50, 0, 2 * Math.PI);
ctx.strokeStyle = "blue";
ctx.lineWidth = 5;
ctx.stroke();
在这个例子中,arc()
方法和上面一样用于画圆,使用 strokeStyle
设置描边颜色,lineWidth
设置描边线条的宽度,最后使用 stroke()
方法描边路径。
四、Canvas 绘制文本
Canvas 还支持在图形上绘制文本。下面介绍两个绘制文本的方法。
1、 fillText()
fillText(text, x, y, maxWidth)
方法用于以给定颜色填充文本,x 和 y 表示文本的起始坐标,maxWidth
表示文本允许的最大宽度,如果文本超出最大宽度,则文本会被自动缩放到适合宽度。示例代码如下:
ctx.font = "30px Arial";
ctx.fillStyle = "blue";
ctx.fillText("Hello, World!", 50, 100);
在这个例子中,使用 font
属性设置文本字体和大小,使用 fillStyle
设置填充颜色,使用 fillText()
方法绘制文本,传入要绘制的文本、文本起始坐标和最大宽度。
2、 strokeText()
strokeText(text, x, y, maxWidth)
方法用于以给定颜色描边文本,示例代码如下:
ctx.font = "30px Arial";
ctx.strokeStyle = "red";
ctx.strokeText("Hello, World!", 50, 100);
在这个例子中,同样使用 font
属性和 strokeStyle
属性设置文本风格和颜色,使用 strokeText()
方法描边文本。
五、Canvas 绘制图片
Canvas 还支持在图像上绘制图片。要在 Canvas 上绘制图片,需要先加载图片并将其存储到 Image 对象中。下面介绍两个绘制图片的方法。
1、drawImage()
drawImage(image, x, y)
方法可以在 Canvas 上绘制图片,需要传入 Image 对象、图片位置的 x 坐标和 y 坐标。示例代码如下:
const img = new Image();
img.src = "https://img.yzcdn.cn/vant/cat.jpeg";
img.onload = function() {
ctx.drawImage(img, 50, 50);
}
在这个例子中,创建一个 Image 对象,设置图片的 src 属性,加载图片后将其绘制到 Canvas 上。绘制使用 drawImage()
方法,传入 Image 对象和图片起始坐标。
2、createPattern()
createPattern(image, type)
方法可以创建一个模式,可以用于填充或描边。需要传入 Image 对象和模式类型。示例代码如下:
const img = new Image();
img.src = "https://img.yzcdn.cn/vant/cat.jpeg";
img.onload = function() {
const pattern = ctx.createPattern(img, "repeat");
ctx.fillStyle = pattern;
ctx.fillRect(0, 0, canvas.width, canvas.height);
}
在这个例子中,创建一个 Image 对象,加载图片后使用 createPattern()
方法创建一个重复填充模式,传入 Image 对象和模式类型。然后使用 fillStyle
属性设置填充颜色,使用 fillRect()
方法填充整个 Canvas 区域。
六、Canvas 动画效果
利用 Canvas 可以方便地实现各种动画效果。主要借助的是定时器的 setInterval() 和 setTimeout() 方法以及上文提到的 Canvas 常用方法。
1、setInterval() 实现动画
setInterval()
方法会定期调用函数,以达到动画效果。该方法接受两个参数:第一个参数是要调用的函数,第二个参数是调用函数之间的时间间隔(以毫秒为单位)。
let x = 0;
setInterval(() => {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, 50, 50, 50);
x++;
}, 10);
效果是一个黑色方块在区域内从左到右移动,在这个例子中,使用 setInterval()
方法实现了一个简单的动画效果,每隔 10 毫秒就执行一次函数。函数中每次依次清除整个 Canvas 区域,然后在 Canvas 上绘制一个矩形,通过修改矩形的 x 坐标实现动画效果。
2、requestAnimationFrame() 实现动画
requestAnimationFrame()
方法也可以实现 Canvas 动画效果。与 setInterval() 相比,requestAnimationFrame() 的 优点 在于:它采用系统时间作为时间间隔,不会因为页面的隐藏/显示而导致误差,同时可以更好地与浏览器的渲染机制配合;而 setInterval() 每次执行的时间间隔是固定的,存在误差,对系统负荷也会产生一定的影响。
let x = 0;
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillRect(x, 50, 50, 50);
x++;
requestAnimationFrame(animate);
}
animate();
效果跟setInterval()
一样,在这个例子中,使用 requestAnimationFrame()
方法,实现了一个矩形动画。在函数 animate()
中,每次依次清除整个 Canvas 区域,然后绘制一个矩形,通过修改矩形的 x 坐标实现动画效果。最后,在函数调用的最后,使用 requestAnimationFrame()
方法递归调用 animate()
函数,使得动画效果可以循环播放。
七、Canvas 使用注意事项
在使用 Canvas 前,需要注意以下几点:
-
Canvas 是一种自由绘制工具,可以通过 JavaScript 动态绘制各种图形,但也容易出现因为**
代码逻辑错误
**导致图形无法正常显示或报错等情况,需要小心谨慎使用。 -
在绘制图像时,请注意
浏览器的性能和兼容性
,对于一些需要动态效果的图形如动画,应该使用合适的方式来进行优化。同时,要考虑浏览器的兼容性,避免使用一些只支持较新版本浏览器的动画特效。 -
在 Canvas 的使用过程中,需要特别注意
刷新频率
,高刷新率可能会对电脑和移动设备的性能造成一定影响,同时也可能会影响使用体验。在绘制过程中借助requestAnimationFrame()
方法可以实现更平滑的动画效果,避免不必要的耗能。
八、利用Canvas绘制挂钟(原理-绘制弧形)- 简单练习
利用 Canvas 绘制挂钟是一个常见的练习,也是为了演示 Canvas 的绘制弧形功能。下面我们来一步一步实现。
首先,我们需要在 HTML 中添加一个 Canvas 标签,并设置好宽度和高度,如下所示:
<canvas id="clock" width="200" height="200"></canvas>
接下来,我们可以在 JavaScript 中获取该 Canvas 节点,获取它的上下文(context),并开始对 Canvas 进行绘制:
const canvas = document.getElementById("clock");
const ctx = canvas.getContext("2d");
1、 还原坐标系
Canvas 默认的 (0, 0) 坐标是位于左上角的。为了便于我们绘制,我们需要将坐标系移动到 Canvas 的中心点。
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
// 将坐标系移动到中心点
ctx.translate(centerX, centerY);
2、 绘制背景
接下来,我们需要绘制钟表的背景。在绘制背景之前,我们需要设置钟表的半径和文本的样式。文本的样式可以通过 font 属性进行设置,如下所示:
const radius = canvas.width / 2 - 5; // 时钟的半径
ctx.font = "bold 14px Arial"; // 设置文本样式
ctx.textAlign = "center"; // 设置文本对齐方式
ctx.textBaseline = "middle"; // 设置文本基线为中间
接下来,我们可以在画布上用圆形绘制钟表的外框,并在轮廓上用数字表示每个小时的位置。这里我们可以使用 for 循环和一些数学计算来绘制每个刻度和数字。
// 绘制钟表轮廓
ctx.beginPath(); //开启路径
ctx.arc(0, 0, radius, 0, 2 * Math.PI); // 绘制圆形
ctx.stroke(); // 画线填充
// 绘制钟表数字
for (let i = 1; i <= 12; i++) {
const angle = i * Math.PI / 6; // 分成12份
ctx.rotate(angle);
ctx.translate(0, -radius + 15); // 将原点向上平移
ctx.rotate(-angle);
ctx.fillText(i.toString(), 0, 0);
ctx.rotate(angle);
ctx.translate(0, radius - 15); // 将原点向下平移
ctx.rotate(-angle)
}
在这里,我们使用 arc()
方法绘制了一个圆形轮廓,并在 for
循环中,使用 rotate()
方法旋转坐标系,依次绘制每个小时的刻度和数字。具体地,我们先将坐标系旋转到目标位置,然后将原点向上平移一定距离,绘制数字,最后再将原点平移回来。
3、 绘制时钟指针
接下来,我们需要绘制时针、分针、秒针。在绘制指针之前,我们需要计算各指针的长度、方向和旋转角度。以时针为例,我们可以通过以下代码计算出时针指向的角度和长度:
const hour = now.getHours();
const minute = now.getMinutes();
const second = now.getSeconds();
const hourAngle = (hour % 12 + minute / 60 + second / 3600) * Math.PI / 6; //时针的角度
const hourLength = 0.6 * radius; //时针的长度
const hourX = Math.sin(hourAngle) * hourLength;
const hourY = -Math.cos(hourAngle) * hourLength;
在这里,我们使用 getHours()
方法获取当前的小时数,getMinutes()
和 getSeconds()
方法分别获取分钟和秒钟数。然后,我们根据当前时间计算出时针指向的角度和长度,再使用 sin()
和 cos()
方法计算出时针指向的位置。最后,我们可以使用 moveTo()
方法将画笔移动到中心点,再并使用 lineTo()
方法连接时针的位置和中心点来绘制时针。
// 绘制时钟指针
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(hourX, hourY);
ctx.lineWidth = 4;
ctx.stroke();
分针和秒针的绘制方式与时针类似,只是长度和线宽有所不同。最终绘制效果如下:
function drawClock() {
const now = new Date();
const radius = canvas.width / 2 - 5;
ctx.clearRect(-centerX, -centerY, canvas.width, canvas.height); // 每次绘制前清空整个画布
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.stroke();
// 绘制钟表数字
ctx.font = "bold 14px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (let i = 1; i <= 12; i++) {
const angle = i * Math.PI / 6;
ctx.rotate(angle);
ctx.translate(0, -radius + 15);
ctx.rotate(-angle);
ctx.fillText(i.toString(), 0, 0);
ctx.rotate(angle);
ctx.translate(0, radius - 15);
ctx.rotate(-angle)
}
// 绘制时针
const hour = now.getHours();
const minute = now.getMinutes();
const second = now.getSeconds();
const hourAngle = (hour % 12 + minute / 60 + second / 3600) * Math.PI / 6;
const hourLength = 0.6 * radius;
const hourX = Math.sin(hourAngle) * hourLength;
const hourY = -Math.cos(hourAngle) * hourLength;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(hourX, hourY);
ctx.lineWidth = 4;
ctx.lineCap = "round";
ctx.stroke();
// 绘制分针
const minuteAngle = (minute + second / 60) * Math.PI / 30;
const minuteLength = 0.8 * radius;
const minuteX = Math.sin(minuteAngle) * minuteLength;
const minuteY = -Math.cos(minuteAngle) * minuteLength;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(minuteX, minuteY);
ctx.lineWidth = 2;
ctx.stroke();
// 绘制秒针
const secondAngle = second * Math.PI / 30;
const secondLength = 0.9 * radius;
const secondX = Math.sin(secondAngle) * secondLength;
const secondY = -Math.cos(secondAngle) * secondLength;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(secondX, secondY);
ctx.lineWidth = 1;
ctx.strokeStyle = "red"; // 设置颜色
ctx.stroke();
// 绘制中央圆点
ctx.beginPath();
ctx.arc(0, 0, 5, 0, 2 * Math.PI);
ctx.fillStyle = "#333"; // 设置颜色
ctx.fill();
// 循环绘制
setTimeout(drawClock, 1000);
}
drawClock();
4、循环绘制
在完成绘制后,我们需要循环调用 drawClock()
方法来实现时钟的动态效果。在 drawClock()
方法中,我们使用 setTimeout()
方法每隔一秒重新绘制一次时钟,实现时间的刷新和动态效果的展现。
// 循环绘制
setTimeout(drawClock, 1000);
5、最后的效果:(视频我就不展示了,下边有源码,你们可以自己试试)
6、总结
通过本例,我们可以学习到 Canvas 的基本使用方法以及绘制弧形的技巧。绘制弧形可以通过使用 arc()
方法和一些计算来实现。除此之外,本例还展示了时钟绘制的完整流程,包括设置文本样式、计算时钟指针的角度和长度、绘制指针以及循环调用来实现时钟动态效果。希望这个例子可以帮助大家更好地了解和使用 Canvas。
7、完整代码如下,其中注释中有更详细的解释:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Canvas Clock</title>
<style>
body {
background-color: #F5F5F5;
}
canvas {
border: 1px solid #444;
}
</style>
</head>
<body>
<canvas id="clock" width="200" height="200"></canvas>
<script>
const canvas = document.getElementById("clock");
const ctx = canvas.getContext("2d");
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
// 将坐标系移动到中心点
ctx.translate(centerX, centerY);
function drawClock() {
const now = new Date();
const radius = canvas.width / 2 - 5;
ctx.clearRect(-centerX, -centerY, canvas.width, canvas.height); // 每次绘制前清空整个画布
ctx.beginPath();
ctx.arc(0, 0, radius, 0, 2 * Math.PI);
ctx.stroke();
// 绘制钟表数字
ctx.font = "bold 14px Arial";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
for (let i = 1; i <= 12; i++) {
const angle = i * Math.PI / 6;
ctx.rotate(angle);
ctx.translate(0, -radius + 15);
ctx.rotate(-angle);
ctx.fillText(i.toString(), 0, 0);
ctx.rotate(angle);
ctx.translate(0, radius - 15);
ctx.rotate(-angle)
}
// 绘制时针
const hour = now.getHours();
const minute = now.getMinutes();
const second = now.getSeconds();
const hourAngle = (hour % 12 + minute / 60 + second / 3600) * Math.PI / 6;
const hourLength = 0.6 * radius;
const hourX = Math.sin(hourAngle) * hourLength;
const hourY = -Math.cos(hourAngle) * hourLength;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(hourX, hourY);
ctx.lineWidth = 4;
ctx.lineCap = "round";
ctx.stroke();
// 绘制分针
const minuteAngle = (minute + second / 60) * Math.PI / 30;
const minuteLength = 0.8 * radius;
const minuteX = Math.sin(minuteAngle) * minuteLength;
const minuteY = -Math.cos(minuteAngle) * minuteLength;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(minuteX, minuteY);
ctx.lineWidth = 2;
ctx.stroke();
// 绘制秒针
const secondAngle = second * Math.PI / 30;
const secondLength = 0.9 * radius;
const secondX = Math.sin(secondAngle) * secondLength;
const secondY = -Math.cos(secondAngle) * secondLength;
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.lineTo(secondX, secondY);
ctx.lineWidth = 1;
ctx.strokeStyle = "red"; // 设置颜色
ctx.stroke();
// 绘制中央圆点
ctx.beginPath();
ctx.arc(0, 0, 5, 0, 2 * Math.PI);
ctx.fillStyle = "#333"; // 设置颜色
ctx.fill();
// 循环绘制
setTimeout(drawClock, 1000);
}
drawClock();
</script>
</body>
</html>
总结
本文详细介绍了 Canvas 的基本概念、应用以及使用注意事项等方面的内容,希望可以帮助大家更好地了解和使用 Canvas。Canvas 是一种非常有趣的技术,可以在 HTML 中实现各种绚丽多彩的图形和动画效果,对于 Web 前端开发工程师来说也是一种非常重要的技术之一,需要我们细心学习。