引言
Canvas 本身只是 h5 的一个容器标签,本身并没有直接提供绘图功能,而是提供了一个空白的矩形画布,需要使用 JavaScript 来操作 Canvas API 进行图形绘制
Canvas API 提供了一组用于绘制图形、文本、图像等的方法和属性。通过 JavaScript 可以获取到 <canvas>
元素的 2D 或 3D 上下文(context),然后使用上下文来进行绘制操作
Canvas API
在了解和使用 Canvas API 之前,需要先创建 canvas 画布,然后在画布上通过 Canvas API 进行图形绘制,所以下面先给出如何创建画布的案例
<canvas id="myCanvas" width="" height=""></canvas>
除了设置画布宽高,还可以给画布本身添加一些 style 样式
画布创建好之后就可以通过 API 获取画布并进行绘制了,在这之前先科普一下:canvas 是一个二维网格,左上角坐标为(0, 0)
获取画布上下文
创建好画布之后需要获取到画布才能开始绘制,canvas 提供了 getContext API 实现此功能
const canvas = document.getElementById("myCanvas");
let context = canvas.getContext("2d");
绘制基本形状
绘制基本形状,只需要掌握绘制矩形和圆形这两个 Canvas API 即可,其他形状可以通过这个两个 API 变形或者组合而成
绘制矩形
API:fillRect(x, y, width, height)、strokeRect(x, y, width, height)
fillRect(x, y, width, height)
:绘制实心矩形x
:矩形的 x 坐标y
:矩形的 y 坐标width
:矩形的宽度height
:矩形的高度
strokeRect(x, y, width, height)
:绘制空心矩形x
:矩形的 x 坐标y
:矩形的 y 坐标width
:矩形的宽度height
:矩形的高度
context.fillStyle = 'red'
context.fillRect(8, 8, 100, 75);
context.stroke();
context.strokeStyle = 'blue';
context.strokeRect(124, 8, 100, 75);
绘制圆形
API:arc(x, y, r, startAngle, endAngle, anticlockwise)
x
:圆心的 x 坐标y
:圆心的 y 坐标radius
:圆的半径startAngle
:起始角度,以弧度表示endAngle
:结束角度,以弧度表示anticlockwise
:可选参数,指定绘制方向是顺时针还是逆时针,默认是 false(顺时针)
context.arc(58, 141, 50, 0, Math.PI * 2);
context.stroke();
绘制路径
绘制路径,用于进行复杂图形的绘制
API:beginPath()、closePath()、moveTo(x, y)、lineTo(x, y)
beginPath()
:用于起始一条新的路径,清空当前的所有路径以及子路径closePath()
:用于闭合路径,即将路径的起点和终点连接起来,形成一个封闭的形状moveTo(x, y)
:用于将笔触移动到指定的坐标(x, y)
,不画线x
:画笔的 x 坐标y
:画笔的 y 坐标
lineTo(x, y)
:用于将笔触从当前点连接到指定的点(x, y)
,画一条直线x
:画笔的 x 坐标y
:画笔的 y 坐标
context.beginPath();
context.moveTo(58, 199);
context.lineTo(8, 249);
context.lineTo(108, 249);
context.closePath();
context.stroke();
beginPath
最初对于beginPath
用来清空当前的所有路径以及子路径这一描述感到很迷惑,不太清楚它到底有什么作用?如果是单纯的从一个点开始新的绘图,那 moveTo() + closePath() 不就可以实现这个效果?
后来通过一个例子,我便明白了:
// 绘制圆形
context.arc(58, 141, 50, 0, Math.PI * 2);
context.stroke();
// 绘制路径
context.beginPath();
context.moveTo(58, 199);
context.lineTo(8, 249);
context.lineTo(108, 249);
context.closePath();
context.stroke();
上面绘制了两个图形:圆形 + 路径。在绘制圆形时,把圆的形状描绘后便立即调用stroke()
进行图形绘制,如果此时去掉这一行代码,会发现页面不会绘制出圆形,但如果再去掉beginPath()
,你会神奇的发现,圆形出现了,因为在最后一行调用stroke()
时进行了整体绘制
此时,对于beginPath
清空当前的所有路径以及子路径应该就有所领悟了~
绘制文本
API:fillText(text, x, y)、strokeText(text, x, y)
fillText(text, x, y)
:绘制实心文本text
:文本内容x
:文本的 x 坐标y
:文本的 y 坐标
strokeText(text, x, y)
:绘制空心文本text
:文本内容x
:文本的 x 坐标y
:文本的 y 坐标
const text = "Hello, Canvas!";
context.font = "30px Arial";
const textMetrics = context.measureText(text);
const totalHeight = textMetrics.actualBoundingBoxAscent + textMetrics.actualBoundingBoxDescent;
context.fillStyle = 'green';
context.fillText(text, 8, 257 + totalHeight);
context.stroke();
context.strokeStyle = 'purple';
context.font = "30px Arial";
context.strokeText(text, 16 + textMetrics.width, 257 + totalHeight);
绘制图像
API:drawImage(image,x,y)
image
:Image 对象x
:图片的 x 坐标y
:图片的 y 坐标
context.fillStyle = "black";
context.fillRect(8, 265 + totalHeight, 120, 25);
const image = new Image();
image.src = "https://lf-cdn-tos.bytescm.com/obj/static/xitu_extension/static/brand-dark.3111cff6.svg";
image.onload = () => {
context.drawImage(image, 8, 265 + totalHeight)
}
变换
API:translate(x, y)、rotate(deg)、scale(scaleX, scaleY)
translate(x, y)
:用于平移绘图环境的原点rotate(deg)
:用于旋转绘图环境scale(scaleX, scaleY)
:用于缩放绘图环境
// 绘制一个矩形
context.fillStyle = "blue";
context.fillRect(50, 400, 100, 50);
// 平移、旋转、缩放
context.translate(100, 425); // 平移原点到矩形中心
context.rotate(Math.PI / 4); // 旋转 45 度
context.scale(2, 1); // 沿 x 轴缩放两倍,沿 y 轴不变
// 绘制一个变换后的矩形
context.fillStyle = "red";
context.fillRect(-50, -25, 100, 50);
颜色和样式
fillStyle
:用于设置绘制形状时的填充颜色strokeStyle
:用于设置绘制形状的轮廓颜色lineWidth
:用于设置绘制形状的线条宽度
fillStyle、strokeStyle
fillStyle
和strokeStyle
是用于设置形状的填充和轮廓颜色的,这里需要说明一下的是:fillRect()
、strokeRect()
、fillText()
、strokeText()
这 4 个 API 关于设置颜色的这 2 个属性的使用
fillRect
方法用于绘制填充的矩形strokeRect
方法用于绘制矩形的轮廓fillText
方法用于绘制填充的文本strokeText
方法用于绘制文本的轮廓
绘制的填充形状,只能使用fillStyle
,因为它会影响填充颜色;而对于绘制的轮廓形状,也只能使用strokeStyle
,因为它会影响轮廓颜色;而对于arc
、path
绘制的形状,fillStyle
和strokeStyle
就都适用,但是也需要结合fill()
和stroke()
来实现图形绘制
fill()
绘制填充图形,可以通过fillStyle
改变填充色stroke()
绘制图形描边,可以通过strokeStyle
改变描边色
动画
API:requestAnimationFrame(callback)
requestAnimationFrame(callback)
:用于在下一次浏览器重绘前执行指定函数callback
:要在每一帧中调用的函数
requestAnimationFrame
返回一个整数值,通常存储在变量animationId
中。这个值可以用于取消动画帧请求,使用cancelAnimationFrame(animationId)
let x = 8;
let color = 0;
function draw() {
// 清除画布
context.clearRect(8, 550, canvas.width, canvas.height);
// 绘制矩形
context.fillStyle = `hsl(${color}, 100%, 50%)`;
context.fillRect(x, 550, 100, 50);
// 更新位置
x += 2;
// 更新颜色
color = (color + 1) % 360;
// 使用 requestAnimationFrame 递归调用 draw 函数
requestAnimationFrame(draw);
}
draw()
清除和保存状态
API:clearRect(x, y, width, height)、save()、restore()
clearRect(x, y, width, height)
:清除矩形区域,如:clearRect(0, 0, canvas.width, canvas.height) 清除整个画布save()
:保存当前状态restore()
:恢复之前保存的状态
最终效果图
本部分是汇总了之前的代码示例后的最终效果图
小结
本篇文章是对 Canvas API 的综合概述,主要是了解 Canvas 提供了哪些功能、可以绘制什么形状以及如何去绘制这些形状,然后在下一篇文章Canvas 新手进阶篇将会通过一个实例来进一步使用和理解 Canvas
- 11.16
- Canvas 新手进阶篇 敬请期待