上节文章中,给大家分享了canvas
最基础的用法,包括绘制线条、控制渲染方式、绘制图形、作用域、添加阴影、清理、剪切等功能,本节将继续为大家分享canvas
的基础用法,同时也是最后一节基础知识分享,之后的内容,我们将会进入到对webgl
的分享中。
1. 文本绘制
首先我们要提到的是绘制文本,在canvas
的开发过程中,文本的内容是肯定会存在的。本小节就来给大家分享下如何渲染文本。
1.1 绘制空心和实心文本
canvas
中提供了两种绘制文本的方法,分别是绘制实心文本和空心文本,它们的方法分别是:
- strokeText(text, x, y, maxWidth): 绘制空心文本
- fillText(text, x, y, maxWidth): 绘制实心文本
参数介绍:
- text: 要绘制的文本内容
x, y
: 坐标点,文本左上角的坐标点- maxWidth: 允许渲染的最大像素宽度
栗子:
// 绘制实心文本c.fillText('hello world', 100, 100); // 将 hello world 这个内容从 100 100 这个点开始渲染。// 绘制空心文本c.strokeText('hello world', 200, 200);
如果这里你的字体是默认大小,可能会看不到空心效果。改变字体大小在下文中有分享到。
1.2 改变文本样式
如果我们想修改字体的颜色,可以根据 绘制图形 一节中的方法,使用 strokeStyle、fillStyle
来修改。
1. 要设置实心文本字体为蓝色
c.fillStyle = 'blue';c.fillText('hello world', 100, 100);
2. 要设置空心字体为红色
c.strokeStyle = 'yellow';c.strokeText('hello world', 200, 200);
1.3 改变文本大小和字体样式
修改字体大小和字体样式需要用到 font = '字体大小 字体样式’
属性。
如:把字体改为 宋体 40px。
c.font = '40px 宋体';
如果是特殊的字体,会出现不支持的现象。
1.4 修改文本对齐方式
文本对齐方式分为 垂直 和 水平 对齐方式。
1. 垂直方向对齐。
这里需要用到 textBaseLine
这个属性。意为按照基线对齐。它有6个值,分别是:
- alphabetic: 默认值,意为普通的字母基线。可理解为四线三格的第三条线。
- top:文字头部对齐基线
- hanging:悬挂基线,与top稍有不同
- middle:文字中部对齐
- ideographic:表意基线。稍难理解,可看示意图
- bottom:文字底部对齐基线
示例:
// 首先我们画一条基准线,让文字按照这条线对齐c.strokeStyle = 'blue';c.moveTo(5, 100);c.lineTo(700, 100);c.stroke();c.font = '20px 宋体';// 枚举可用的对齐方式。c.textBaseline = 'top';c.fillText('Top', 5, 100);c.textBaseline = 'bottom';c.fillText('Bottom', 100, 100);c.textBaseline = 'middle';c.fillText('Middle', 200, 100);c.textBaseline = 'alphabetic';c.fillText('Alphabetic', 300, 100);c.textBaseline = 'hanging';c.fillText('Hanging', 400, 100);c.textBaseline = 'ideographic';c.fillText('ideographic', 500, 100);
示例图:
2. 水平居中
水平居中需要使用 textAlign
属性。同样也是基于基准线对齐,有5个属性值。
- start: 默认。文本在指定的位置开始。
- end: 在指定的位置结束
- center: 文本中心被放在指定位置
- left: 文本左对齐
- right: 文本右对齐
栗子:
// 创建基准线c.strokeStyle = 'blue';c.moveTo(150, 20);c.lineTo(150, 400);c.stroke();c.font = '30px 宋体';// 枚举可用的对齐方式。c.textAlign = 'start';c.fillText('start', 150, 50);c.textAlign = 'end';c.fillText('end', 150, 100);c.textAlign = 'left';c.fillText('left', 150, 150);c.textAlign = 'center';c.fillText('center', 150, 200);c.textAlign = 'right';c.fillText('right', 150, 250);
示例图:
3. 不固定宽高的画布水平居中
对于宽度不固定的画布,我们使用 textAlign
的作用就不太大了。因为此时我们需要根据画布的宽度进行实时计算。此时我们需要获得两个数值。画布宽度和字体宽度。画布宽度比较简单,使用 ctx.width
就可以获取。
字体的宽度。需要用到 measureText(text)
方法。此方法可根据你设置的字体大小来返回传入文本的像素宽度。
栗子:
c.font = '20px 宋体'const textData = c.measureText('hello world');console.log(textData.width) // 84
设置字体宽度为 20px
,则渲染后的 hello world
占据的像素宽度为 84px
(不同浏览器之间会有差异)
这样我们就可以得到水平居中的计算方式
文本x坐标 = (画布宽 - 文本宽)/ 2
const x = (ctx.width - c.measureText('hello world')) / 2;
2. 动画
2.1 状态保存与恢复
分享动画之前 ,我们先来介绍 save 和 restore
这两个方法。因为我们在处理动画的过程中,避免不了对画布进行旋转、平移和缩放的操作。从而导致之前或之后的绘制出现错乱。而`save 和 restore
这两个方法就可以避免这个问题。
save
: 保存当前canvas
的状态。restore
: 恢复之前保存的状态。
2.2 变换
说到动画,无非就是对图形的旋转、缩放、平移这几项内容。canvas
中提供了一系列的方法。
- translate(x, y): 平移。可改变当前画布的原点位置。
- rotate(deg) :旋转。其中 deg 代表的是弧度制。(角度转弧度请看初始canvas(一)的内容)
- scale(x,y): 缩放,
x
代表x轴缩放。y
代表y轴缩放。
栗子:
// 原始矩形c.save()c.fillRect(10, 10, 100, 100);c.restore()// 平移50pxc.save()c.translate(50, 50);c.fillRect(10,10,100,100);c.restore()// 旋转45度c.save()c.rotate(45 * Math.PI / 180);c.fillRect(210, 110, 100, 100)c.restore()// x轴缩放0.5 y轴缩放1.1c.save()c.scale(0.5, 1.1)c.fillRect(410, 210, 100, 100)c.restore()
注意:translate
平移之后是可以改变画布原点的位置的,此时如果我们需要让某个图形围绕自身旋转,则需要将图像的中心点位于画布圆点上。如下方代码所示:
// 将画布中心移入到 50,50 这个点c.translate(50, 50);setInterval(() => {
// 每次绘制之前先清空画布,这里的原点已经在50,50这个位置了。所以需要从 -50这里开始清理。 c.clearRect(-50, -50, ctx.width, ctx.height);
// 每次旋转 1 度 c.rotate(Math.PI / 180);
// 绘制实心矩形。 c.fillRect(-25,-25, 50,50);}, 16)
这里就可以得到一个围绕自身旋转的实心矩形。
2.3 transform 矩阵操作
方法接收 6
个参数。transform(a,b,c,d,e,f)
其中,
- 平移:涉及到
e, f
两个参数 - 缩放:涉及到
a, d
两个参数 - 拉伸:涉及到
b, c
两个参数 - 旋转:涉及到