字体
文本元素通过字体资源绘制文字。资源由描述字形的 .json 和保存字形的一张或多张 .png 纹理页组成,采用多通道有符号距离场(MSDF)。字形保存为距离场而非普通像素,因此不同字号均可保持清晰,每种字体只需一份资源。
创建字体资源
在编辑器中
上传 .ttf、.ttc、.otf 或 .dfont 文件。编辑器在浏览器中生成字体,并创建包含源文件、.json、.png 纹理页及字体资源本身的文件夹。
选中字体资源后,在检查器中选择字符。CHARACTER PRESETS 可加入 Latin、Latin Supplement、Cyrillic 和 Greek 等字符集;CUSTOM CHARACTER RANGE 通过十六进制 Unicode 码点加入范围;Characters 列出将包含的字符。单击 REGENERATE FONT ASSETS 重新生成。如果源字体缺少某些字符,检查器会列出,并提供复制字符或编码的按钮。
旧版编辑器创建的字体在首次重新生成时会转换为当前格式,此过程不可撤销。其他选项详见字体资源检查器。
使用 font-tools
不使用编辑器时,可以通过编辑器自身使用的生成器 font-tools 创建:
-
Web 应用。 打开 playcanvas.github.io/font-tools,拖入 TTF 或 OTF,选择字符与字形尺寸,以实际 PlayCanvas 文本预览结果并下载文件。全部在浏览器中运行,不上传字体。
-
命令行。 从终端生成资源:
npx @playcanvas/font-tools MyFont.ttf --charset latin-ext -o assets/fonts/myfont此命令写入
myfont.json和myfont.png。字符较多时会生成myfont1.png、myfont2.png等额外页。
| 选项 | 默认值 | 效果 |
|---|---|---|
-o, --out <path> | 字体名称 | 不含扩展名的输出路径 |
--charset <spec> | ascii | 预设 ascii、latin、latin-ext、cyrillic、greek,或直接指定字符 |
--size <px> | 64 | 图集中每个字形单元的尺寸 |
--pxrange <px> | 8 | MSDF 距离范围,单位为像素 |
--name <face> | 输出名称 | 写入 .json 的字体名称 |
--no-kerning | 启用字偶距 | 不包含字偶距数据 |
font-tools 默认读取字偶距对,编辑器则不会,因此 font-tools 资源的文本间距可能略紧。该工具以 MIT 许可开源,还提供 JavaScript API,可集成到自己的工具中。
选择字符
字体资源仅包含生成时选择的字符,其他字符会显示为空格并产生控制台警告。应包含全部所需字符,包括重音字母、“” 和 … 等标点、货币符号,以及所有本地化语言的字符。
每个字符都会占用图集空间。中文、日文和韩文所需的数千字符会使资源增大、加载变慢。宜只纳入实际使用的字符,而非整个文字系统;各语言字符集差异较大时,使用独立本地化字体。
使用字体资源
将 .json 与 .png 页放在一起,并保持相同基础文件名。加载器会根据 JSON URL 推导各页 URL,并一起加载。
- 引擎
- 编辑器
- React
- Web Components
// Loading myfont.json also loads myfont.png, and any further pages
const font = new pc.Asset('myfont', 'font', { url: 'fonts/myfont.json' });
app.assets.add(font);
await new Promise((resolve) => {
font.ready(resolve);
app.assets.load(font);
});
const label = new pc.Entity('label');
label.addComponent('element', {
type: pc.ELEMENTTYPE_TEXT,
fontAsset: font.id,
text: 'Hello, World!',
anchor: [0.5, 0.5, 0.5, 0.5],
pivot: [0.5, 0.5]
});
screen.addChild(label);
创建应用时注册 pc.FontHandler,以支持字体加载。
无需编写加载代码,将字体资源拖到文本元素 Font 字段即可,详见文本元素。
通过 useFont 加载 .json,再将资源传给文本 <Element>:
import { Entity } from '@playcanvas/react';
import { Element } from '@playcanvas/react/components';
import { useFont } from '@playcanvas/react/hooks';
export function Label() {
const { asset: font } = useFont('fonts/myfont.json');
if (!font) return null;
return (
<Entity name="label">
<Element type="text" fontAsset={font} text="Hello, World!"
anchor={[0.5, 0.5, 0.5, 0.5]} pivot={[0.5, 0.5]} />
</Entity>
);
}
loading 和 error 状态处理详见加载资源。
声明资源时指定 type="font",否则 .json 会按普通 JSON 加载,然后通过 id 引用:
<pc-app>
<pc-asset id="myfont" type="font" src="fonts/myfont.json"></pc-asset>
<pc-scene>
<pc-entity name="camera">
<pc-camera></pc-camera>
</pc-entity>
<pc-entity name="screen">
<pc-screen screen-space scale-mode="blend" reference-resolution="1280 720"></pc-screen>
<pc-entity name="label">
<pc-element type="text" font-asset="myfont" text="Hello, World!"
anchor="0.5 0.5 0.5 0.5" pivot="0.5 0.5"></pc-element>
</pc-entity>
</pc-entity>
</pc-scene>
</pc-app>
表情
MSDF 字形只有单色,不能绘制彩色表情。尚未收录于 API 参考的 pc.CanvasFont 可使用浏览器字体,将文字及表情绘入纹理。它属于位图字体,创建尺寸应至少等于最终字号,并在使用前加入所需字符:
const emojiFont = new pc.CanvasFont(app, {
fontName: 'Arial',
fontSize: 64,
color: new pc.Color(1, 1, 1),
width: 256,
height: 256
});
emojiFont.createTextures('Well done! 🎉');
const message = new pc.Entity('message');
message.addComponent('element', {
type: pc.ELEMENTTYPE_TEXT,
text: 'Well done! 🎉',
fontSize: 32,
anchor: [0.5, 0.5, 0.5, 0.5],
pivot: [0.5, 0.5]
});
message.element.font = emojiFont;
screen.addChild(message);
首次 createTextures 创建纹理。设置包含新字符的文本前,应先通过 updateTextures 加入这些字符。
另请参阅
- 文本元素:绘制、换行、适配和样式。
- 本地化:译文与各语言字体。
- 字体资源检查器:编辑器中的全部字体选项。
- font-tools:源码、命令行选项和 API。