闻乐 发自 凹非寺
量子位 | 公众号 QbitAI
请问可以入职《预言家日报》吗?
谁能想到,哈利波特的魔法报纸,居然被本麻瓜用前端做出来了(doge)。
这个大段文本和喷火龙插画的实时动态环绕混排,效果直接给到一个夯
。
Bad Apple也被玩出了文字影绘的新花样,经典果然永不过时!
如此丝滑不卡顿的文本渲染直接闪瞎眼了有没有?
这是这两天爆火的开源项目Pretext,一个专为AI时代打造的新型文本测量与布局库。
上线短短两天狂揽*12k star。
Pretext完全绕过了传统的DOM测量方式(浏览器给JS提供的、用来读写和修改网页内容的接口),纯Java/Type编写,专门搞文本排版计算。
也就是说它不会调用getBoundingClientRect或offsetHeight这类会触发页面重排的API,用纯数学计算就能完成文本布局。
而且中文、英文、小语种……甚至各种奇怪的表情符号都能精准处理。
还能针对Chrome、Safari、Firefox等各类浏览器在排版细节上的差异行为进行专门适配。
比如阿拉伯语标点合并方式、Emoji宽度处理等,计算结果可以自由输出到DOM、Canvas、SVG。
项目的核心开发者,是前React核心之一、ReasonML和Midjourney前端背后的男人ChengLou。
果然,大佬就是大佬(佩服.jpg)。
丝滑,太丝滑
那这个库到底能玩出什么花来?咱先挨个盘一盘。
比如,在展示海量文本列表时,传统方案必须频繁查询DOM才能知道每一项高度,极易卡顿。
而Pretext可以提前算出所有文本的精确高度,让列表在滚动、缩放时,能够快速判断哪些内容需要显示,实现超高流畅度的虚拟列表效果。
它可以根据文本内容自动计算出最紧凑的宽度,让气泡完美贴合文字,无需DOM测量即可实现类似微信、IM工具的自适应气泡样式,实现缩放效果。
多栏杂志式布局可以让文本在多列之间自动流畅流动,窗口大小变化时,就能实时重新排版,带动态响应的那种。
当然了,还有炫技的文字、插画混排,哪怕人物在画面中动态移动,文本也会毫秒级自动避让、实时重排。
如此丝滑,难怪网友:根本停不下来!
告别DOM
现在咱知道Pretext能做出什么了,那就要问了,它凭啥能做到这些?
这就得从传统方式的老大难说起了。
在Web里,想知道一段文字有多高,标准做法就是把它塞进DOM,然后调getBoundingClientRect 或offsetHeight去量。
这俩API一调用,浏览器就得停下来重新计算整个页面的布局才能给出答案。
这个过程叫布局回流。
一个段落当然没事,但假如你在做一个虚拟滚动列表,需要同时测量500条评论的高度,那每帧就可能被占掉30毫秒以上。
而浏览器渲染一帧的预算总共只有16.67毫秒,结果就是卡成PPT。
那Pretext是怎么绕开这个死胡同的呢?
它的思路贼简单——
把重活只做一次,剩下的全是纯数学运算。
它把所有文本处理拆成两个阶段。
第一阶段叫 prepare,是一次性预处理。
对文本分词、应用排版规则,再用Canvas的measureText去量每个片段的宽度。
不过这一步完全不会触发布局,只是问浏览器字体引擎要数据,然后把所有词宽数据缓存起来。
第二阶段叫layout,是一条纯粹的数学热路径。
拿着缓存好的词宽数据,在给定容器宽度下做换行运算,没有DOM读取,没有Canvas调用,也没有字符串分配,可以被无限次反复调用。
这样下来,处理500段文本,prepare大约需要17毫秒,但只跑一次;
而layout只需要0.10毫秒,每次窗口缩放都能重新触发。
相比传统DOM测量方式,这可是300到600倍的速度差距。
有了这套机制打底,Pretext就可以放心地把算力全花在排版本身了。
多语言、表情符号、双向文本混排,适配各类浏览器的特殊排版细节……
而且它只负责计算,不负责渲染,所以算出来的结果可以自由输出到DOM、Canvas、SVG,甚至未来的服务端渲染。
Pretext的接入方式也很简单,安装通过npm完成:
npm install @chenglou/pretext
想在项目里用Pretext,只需要:
import { prepare, layout } from “@chenglou/pretext”
典型的使用流程分为两步。
先用prepare对文本进行一次预处理,得到一个包含词宽等数据的句柄;
之后在任何需要测量布局的地方调用layout,传入容器宽度和行高即可获得总高度与行数。
对于需要逐行控制布局的场景,比如实现文字绕开特定形状(喷火龙),可以改用高级API。
prepareWithSegments返回更细粒度的数据结构,配合layoutNextLine逐行获取排版结果,每一行都能单独指定不同的可用宽度。
此外,项目还提供了辅助工具。
setLocale 用于指定区域语言,默认自动适配系统;clearCache 可以在频繁切换字体时主动释放缓存。
只能说,DOM测量,恐怕要江湖再见咯~
项目地址:https://github.com/chenglou/pretext/
参考链接:
[1]https://x.com/_chenglou/status/2037715519277760531
[2]https://x.com/birdabo/status/2038219452337074677