canvas 文字
绘制文本主要使用两个 api。
CanvasRenderingContext2D.fillText()是 Canvas 2D API 在 (x, y) 位置填充文本的方法。如果选项的第四个参数提供了最大宽度,文本会进行缩放以适应最大宽度。
js
void ctx.fillText(text, x, y, [maxWidth]);CanvasRenderingContext2D.strokeText()是 Canvas 2D API 在给定的 (x, y) 位置绘制文本轮廓的方法。如果提供了表示最大值的第四个参数,文本将会缩放适应宽度。
js
void ctx.strokeText(text, x, y [, maxWidth]);绘制一个 Hello World
可以看到文字有种被压扁的感觉。因为正常来讲文字会超出 canvas 的区域,但是我们设置了 maxWidth 参数,所以文字会压缩来适应最大宽度。
除此之外,还可以使用 fillText 来填充文本。
vue
<template>
<canvas id="hello-world" width="80" height="100"></canvas>
<canvas id="hello-world3" class="mt-10px" width="200" height="100"></canvas>
<canvas id="hello-world2" class="mt-10px" width="200" height="100"></canvas>
</template>
<script setup lang='ts'>
import { onMounted } from 'vue';
onMounted(() => {
const ctx = (document.getElementById('hello-world') as HTMLCanvasElement).getContext('2d')!
ctx.strokeRect(0, 0, 80, 100)
ctx.font = '48px serif'
ctx.strokeText('hello, world', 0, 50, 80)
const ctx2 = (document.getElementById('hello-world2') as HTMLCanvasElement).getContext('2d')!
ctx2.strokeRect(0, 0, 200, 100)
ctx2.font = '48px serif'
ctx2.fillText('hello', 0, 50)
const ctx3 = (document.getElementById('hello-world3') as HTMLCanvasElement).getContext('2d')!
ctx3.strokeRect(0, 0, 200, 100)
ctx3.font = '48px serif'
ctx3.strokeText('hello', 0, 50)
})
</script>有样式的文本
文本居中方式 textAlign
ctx.textAlign
这里的 textAlign="center"比较特殊。textAlign 的值为 center 时候文本的居中是基于你在 fillText 的时候所给的 x 的值,也就是说文本一半在 x 的左边,一半在 x 的右边(可以理解为计算 x 的位置时从默认文字的左端,改为文字的中心,因此你只需要考虑 x 的位置即可)。所以,如果你想让文本在整个 canvas 居中,就需要将 fillText 的 x 值设置成 canvas 的宽度的一半。

vue
<template>
<canvas id="style-text" width="200" height="200"></canvas>
</template>
<script setup lang='ts'>
import { onMounted } from 'vue';
onMounted(() => {
const ctx = (document.getElementById('style-text') as HTMLCanvasElement).getContext('2d')!
ctx.strokeRect(0, 0, 200, 200)
// 使用和 css 的 font 相同的属性值
ctx.font = '48px serif'
// 如果想让文本在 canvas 水平居中,不仅要设置 textAlign = 'center',还要设置绘制文本的 x 在画布中间。
ctx.textAlign = 'center'
// 基线对齐选项
ctx.textBaseline = 'bottom'
// 文本阅读方向
ctx.direction = 'rtl'
ctx.strokeText('hello', 100, 50)
})
</script>文本垂直居中方式 textBaseline
ctx.textBaseline
js
ctx.textBaseline = "top" || "hanging" || "middle" || "alphabetic" || "ideographic" || "bottom";vue
<template>
<canvas id="textBaseline" width="550" height="550" class="w-full"></canvas>
</template>
<script setup lang='ts'>
import { onMounted } from 'vue'
onMounted(() => {
const ctx = (document.getElementById('textBaseline') as HTMLCanvasElement).getContext('2d')!
ctx.strokeRect(0, 0, 550, 550)
const baselines = ['top', 'hanging', 'middle', 'alphabetic', 'ideographic', 'bottom'] as CanvasTextBaseline[]
ctx.font = '36px serif'
ctx.strokeStyle = 'red'
baselines.forEach((baseline, index) => {
ctx.textBaseline = baseline
const y = 75 + index * 75
ctx.beginPath()
ctx.moveTo(0, y + 0.5)
ctx.lineTo(550, y + 0.5)
ctx.stroke()
ctx.fillText(`Abcdnop 啊瑟瑟发抖 (${baseline})`, 0, y)
})
})
</script>绘制文本的方向 direction
ctx.direction
比如要绘制一个文本 hello。
从左到右绘制:h -> e -> l -> l -> 0。
从右到左绘制:o -> l -> l -> e -> h。
虽然最后呈现的一样,但是绘制字母的顺序不一样。
预测量文本宽度 measureText
当你需要获得更多的文本细节时,下面的方法可以给你测量文本的方法。
js
measureText()将返回一个 TextMetrics 对象的宽度、所在像素,这些体现文本特性的属性。
下面的代码段将展示如何测量文本来获得它的宽度:
js
function draw() {
var ctx = document.getElementById('canvas').getContext('2d');
var text = ctx.measureText("foo"); // TextMetrics object
text.width; // 16;
}