opentype.js 使用与文字渲染

作者:明远湖之鱼日期:2025/10/14

笔者在某个需求实现中使用了 opentype.js 这个库,现将一些使用过程记录在本篇文章中。

opentype.js 是一个 JavaScript 库,支持浏览器和 Node.js,可以解析字体文件,拿到字体信息,并提供一些渲染方法。

虽然名字叫做 opentype.js,但除了可以解析 OpenType,也可以解析 TrueType。

支持常见的字体类型,比如 WOFF, OTF, TTF,像是 AutoCAD 的 shx 就不支持了。

需要注意的是,woff2 字体是用 Brotli 压缩过的文件,需要额外用解压库做解压。 opentype.js 没有提供对应解压 Brotli 的能力,倒是提供了 Inflate 解压能力,所以可以解析 woff 字体。

opentype.js 解析字体

1    // 从 URL 下载字体
2    const response: HttpClientResponse = await makeHttpRequest(url);
3
4    if (!response.status || response.status !== 200) {
5      handleError(`HTTP error! status: ${response.status}`);
6    }
7    // 加载文件字体为二进制数据,然后使用 opentype.js 解析
8    const buffer = response.data as Buffer;
9    const arrayBuffer = buffer.buffer.slice(
10      buffer.byteOffset,
11      buffer.byteOffset + buffer.byteLength
12    );
13    const font = await opentype.parse(arrayBuffer);
14

这个 font 这个对象保存了很多属性,比如所有的 glyph(字形)、一些 table(表)、字体的信息(字体名、设计师等)等等。

image.png

获取字形(glyph)信息

字形(glyph)是一个用于在字体排印中表示一个或多个字符的视觉表征的术语。

1const glyph = font.charToGlyph('A')
2

有了字形,我们就能拿到某个或者某段文本字符串渲染所需要的一些关键信息(width、height、ascender、descender):

1/**
2   * 测量文本宽度
3   * @param text 文本
4   * @param fontUrl 字体URL
5   * @param fontSize 字体大小
6   * @returns 宽度、高度以及字体的上下边界信息
7   */
8  async measureText(
9    text: string,
10    fontUrl: string,
11    fontSize: number
12  ): Promise<FontMetrics> {
13    // 1. 加载字体文件(opentrue
14    const font = await this.loadFontFromUrl(fontUrl);
15
16    // 2. 计算缩放比例:将字体的原始单位(unitsPerEm)转换为实际像素大小
17    //    font.unitsPerEm 通常是 1000 或 2048,表示字体设计时的基准网格
18    //    fontSize 是你想要渲染的大小(比如 32px)
19    //    所以 scale = fontSize / unitsPerEm,用于把字体的“逻辑单位”转为“像素”
20    const scale = fontSize / font.unitsPerEm;
21
22    // 3. 将字符串转换为字形(glyph)数组
23    //    每个字符可能对应一个或多个 glyph(比如连字 "fi")
24    //    glyphs 是字体中实际的图形对象,包含路径、宽度等信息
25    const glyphs = font.stringToGlyphs(text);
26
27    // 4. 计算文本总宽度
28    let width = 0;
29    glyphs.forEach((glyph, i) => {
30      // 如果不是第一个字符,加上前一个字符和当前字符之间的“字距调整”(kerning)
31      // kerning 是为了让某些字符组合(如 "A" 和 "V")看起来更美观,自动缩小间距
32      if (i > 0) {
33        width += font.getKerningValue(glyphs[i - 1], glyph);
34      }
35
36      // 加上当前字形的“前进宽度”(advanceWidth)
37      // 注意:这不是字形的绘制宽度,而是光标移动的距离(包含右侧空白)
38      width += glyph.advanceWidth;
39    });
40
41    // 5. 返回测量结果(全部乘以 scale 转为像素单位)
42    return {
43      // 文本总宽度(含 kerning)
44      width: width * scale,
45
46      // 文本总高度 = ascender(上部) - descender(下部)
47      // ascender 是基线以上部分(如 "b", "h" 的顶部)
48      // descender 是基线以下部分(如 "g", "y" 的底部)
49      height: (font.ascender - font.descender) * scale,
50
51      // 基线以上的高度(正数),可用于垂直对齐计算
52      ascender: font.ascender * scale,
53
54      // 基线以下的高度(通常是负数,但这里保留原值)
55      descender: font.descender * scale,
56    };
57  }
58

image.png

获取文字轮廓(path)

getPaths 计算得到一段字符串中每个 glyph 的轮廓数据。 注意:传入的y坐标确实表示的是基线坐标(baseline),而不是字符的顶部或底部。

1const textPaths = font.getPaths(text, x, y, fontSize);
2

textPaths 是一个 path 数组。 字符串长度为 6,产生了 6 个 glyph(字形),所以一共有 6 个 path 对象。 形状的表达使用了经典的 SVG 的 Path 命令,对应着 command 属性。 TrueType 字体的曲线使用二阶贝塞尔曲线(对应 Q 命令);而 OpenType 支持三阶贝塞尔曲线(对应 C 命令)。

image.png

转成真正能用的path路径,需要调用OpenType.js 暴露的另一个方法:

1textPaths.toPathData(2);
2

image.png

基于生成的 Path 路径与字形信息,我们便能实现文本在某种字体下的 SVG 绘制了,剩下的步骤待读者自行探索。


opentype.js 使用与文字渲染》 是转载文章,点击查看原文


相关推荐


Redis(58)如何配置和查看Redis的慢查询日志?
Victor3562025/10/13

Redis 提供了慢查询日志功能,用于记录执行时间超过指定阈值的命令。这有助于识别和优化性能瓶颈。下面详细介绍如何配置和查看 Redis 的慢查询日志,并结合使用 Java 和 Jedis 进行示例演示。 配置慢查询日志 配置 Redis 的慢查询日志可以通过编辑 redis.conf 文件,或者在运行时使用 CONFIG SET 命令。 在 redis.conf 文件中配置 打开 redis.conf 文件,找到并设置以下参数: slowlog-log-slower-than 10000 #


走进 OpenCV 人脸识别的世界
过往入尘土2025/10/11

引言:走进 OpenCV 人脸识别的世界 在当今数字化时代,人脸识别技术作为生物特征识别领域的关键技术之一,正以前所未有的速度融入人们的生活,展现出巨大的应用潜力与价值。它通过计算机视觉技术对人脸图像或视频中的人脸特征进行提取、分析和比对,从而实现身份识别、验证等功能,广泛应用于安防监控、金融支付、门禁系统、智能交通、社交媒体等诸多领域,为人们的生活和工作带来了极大的便利与安全保障。 在安防监控领域,人脸识别技术可实时监测人员出入情况,对潜在的安全威胁进行预警。例如,在机场、火车站等交通枢纽


AI辅助制作宣传视频
Enabler_Rx2025/10/10

首先写好文字稿子,然后用google gemini模型生成音频。可以选择很多种人声,我选择了language English(US)和callirrhoe的发声,模型文生音频链接: https://cloud.google.com/text-to-speech?hl=zh-CN 然后下载音频文件 使用Microsoft Clipchamp打开音频文件,插入图像内容,可以调节音频速度,加入字幕等 然后导出生成文件 完成!


前端必看!12个JS神级简写技巧,代码效率直接飙升80%,告别加班!
刘大华2025/10/8

前言 哈喽大家好,我是大华。 在日常开发中,我们经常会遇到一些重复、冗长的代码。写起来费劲,读起来费神,维护起来更是头疼。而且代码越复杂,性能可能越受影响。 那有没有办法让代码更简洁、清晰又高效呢? JavaScript提供了许多现代语法特性,合理使用这些简写技巧,不仅能大幅减少代码量,还能提升可读性和执行效率。 很多资深前端都在用,这篇文章整理了 12 个最实用的 JS 简写技巧,并结合实际场景进行优化和补充,帮助你写出更优雅的代码。 1. 短路运算符:替代简单的 if 判断 以前我们这样写


【玩泰山派】4、制作ubuntu镜像-(5)总结制作ubuntu22.04镜像+5.10内核流程
风为你而吹2025/10/7

文章目录 前言rk镜像概念rk镜像构成生成sd卡镜像 制作根文件系统流程概述文件概述执行流程执行./mk-base-debian.sh执行mk-buster-rootfs.sh执行./mk-image.sh 总结 使用docker容器基于鲁班猫的仓库制作泰山派的ubuntu22.04根文件系统前言流程制作docker镜像启动docker容器进入容器进入容器后执行step1.准备step2.构建基础 Ubuntu 系统。step3.添加 rk overlay 层,并打包ubuntu


DrissionPage爬取汽车之家:(车名 + 颜色 + 车辆型号/续航里程)
python全栈蛇行者2025/10/5

DrissionPage爬取汽车之家 效果展示 项目概述与背景 在当今大数据时代,网络数据采集已成为获取信息的重要手段。本教程将全面详细介绍如何使用Python的DrissionPage库结合其他工具爬取汽车之家网站(https://www.autohome.com.cn/price/levelid_1)的汽车数据。汽车之家作为国内领先的汽车资讯平台,包含了丰富的汽车信息数据,这些数据对于汽车市场分析、竞品研究、价格监控等具有重要价值。 本项目旨在通过自动化技术手段,高效地采集汽


UNIX下C语言编程与实践5-C 语言编译器 cc(gcc/xlc)核心参数解析:-I、-L、-D 的使用场景与实例
迎風吹頭髮2025/10/4

一、引言:为什么需要关注 cc 编译器参数? 在 UNIX 环境下,C 语言编译器(如 gcc、xlc,统一简称 cc)是开发的核心工具。当项目规模超过单个文件、依赖第三方库或需要条件编译时,仅靠默认编译命令(如 cc main.c -o main)会频繁遇到「头文件找不到」「库链接失败」「宏定义未生效」等问题。 本文聚焦 cc 编译器中最核心的三个参数:-I(加载头文件路径)、-L(加载库文件路径)、-D(宏定义),结合实际项目案例解析其作用、使用场景及常见问题,同时拓展其他实用参数,帮助


介绍一种新的向量存储格式:DiskBBQ
Elastic 中国社区官方博客2025/10/3

作者:来自 Elastic Benjamin Trent, John Wagster 及 Ignacio Vera Sequeiros 介绍 DiskBBQ,一种 HNSW 的替代方案,并探讨何时以及为何使用它。 测试 Elastic 的领先开箱即用能力。深入我们的示例笔记本,开始免费的云试用,或立即在本地机器上尝试 Elastic。 DiskBBQ 是 Inverted Vector File (IVF) 索引的进化版。它是 Hierarchical Navigable Sm


vue2到vue3快速上手入门
cz橙2025/10/2

vue3 需要会vue2,该文档笔记基于黑马的课,进阶快速入门vue3 vue3 官方文档:https://v3.cn.vuejs.org/ main.js改变 import { createApp } from 'vue' import App from './App.vue' const app = createApp(App) app.mount('#app') /* 挂载app到id为app的元素上 */ 不需要new Vue(),直接createApp(App) App.


Mock数据与真实API的无缝切换:联调阶段的核心技术
_5792025/10/2

在现代软件开发中,尤其是在多系统、多平台的应用环境下,如何高效地进行数据集成和接口联调一直是一个挑战。随着开发流程的不断优化,Mock数据和真实API的无缝切换成为了开发和测试过程中的一个关键环节。本文将详细探讨如何实现Mock数据与真实API的无缝切换,并分享在联调阶段的核心技术及最佳实践。??Mock数据与真实API的背景概述在开发初期,API的设计和实现往往会滞后于前端界面的开发。此时,为了保证前端开发能够顺利进行,开发人员通常会使用Mock数据来模拟真实API的响应。这种方法可以帮助开发

首页编辑器站点地图

Copyright © 2025 聚合阅读

License: CC BY-SA 4.0