Show HN: React Hooks,基于字体度量,在渲染前预测文本高度

2作者: ahmadparizaad4 个月前
我构建了 @pretext-studio/core 来解决一个特定的烦恼:浏览器在渲染文本块之后才会告诉你它有多高。这迫使你陷入“先渲染后测量”的循环(这会导致布局偏移),或者使用像 max-height: 9999px 这样的 hack 来实现手风琴动画(这使得缓动看起来不正确,因为动画运行在 9999px 上,而不是实际内容的高度)。 这个库封装了 @chenglou/pretext,一个纯 JavaScript 文本布局引擎,它使用通过 Font Metrics API 加载一次的字体指标来复制浏览器的换行算法。从那里开始,计算高度就变成了算术运算——没有 DOM,没有 getBoundingClientRect,没有重排。一个 prepare() 调用大约需要 0.03ms;一个 layout() 调用不到 0.01ms。结果缓存在模块级别的 LRU 映射中,因此对相同字体/大小对的重复调用几乎是免费的。 主要钩子有 useTextLayout(给定宽度的块的高度 + 行数),useBubbleMetrics(找到保留行数的最小宽度,这消除了你从 CSS fit-content 获得的空白),以及 useStableList(在绘制之前预先计算项目列表的高度,这对于虚拟列表和砌体布局很有用)。还有一个 MeasuredText 嵌入式组件,带有一个调试叠加层,它在实际渲染的文本上绘制预测的行边界,这样你就可以看到预测在哪里发散。 诚实的限制:它只适用于你可以加载指标的字体,因此任意的系统字体或行为不佳的可变字体可能会出现偏差。每个钩子上的 isReady 标志在字体指标加载之前为 false,因此在使用 Web 字体时,你需要对其进行渲染控制。它也还没有处理 white-space: pre-wrap。欢迎反馈——特别是如果你在使用字体加载或非拉丁脚本时遇到了边缘情况。 GitHub: <a href="https://github.com/ahmadparizaad/pretext-studio-core" rel="nofollow">https://github.com/ahmadparizaad/pretext-studio-core</a> — npm: @pretext-studio/core
查看原文
I built @pretext-studio&#x2F;core to solve a specific annoyance: the browser won&#x27;t tell you how tall a text block is until after it renders. This forces you into either a render-then-measure cycle (which causes layout shift) or hacks like max-height: 9999px for accordion animations (which makes easing look wrong because the animation runs over 9999px, not the actual content height).<p>The library wraps @chenglou&#x2F;pretext, a pure-JS text layout engine that replicates the browser&#x27;s line-breaking. algorithm using font metrics loaded once via the Font Metrics API. From there, computing height is arithmetic — no DOM, no getBoundingClientRect, no reflow. A prepare() call runs in ~0.03ms; a layout() call in under 0.01ms. Results are cached in a module-level LRU map so repeated calls for the same font&#x2F;size pair are nearly free.<p>The main hooks are useTextLayout (height + line count for a block at a given width), useBubbleMetrics (finds the tightest width that preserves line count, which eliminates the dead space you get from CSS fit-content), and useStableList (pre-computes heights for a list of items before paint, useful for virtualized lists and masonry layouts). There&#x27;s also a MeasuredText drop-in component with a debug overlay that draws predicted line boundaries over actual rendered text so you can see where predictions diverge.<p>The honest limitation: it only works with fonts you can load metrics for, so arbitrary system fonts or poorly-behaved variable fonts may drift. The isReady flag on every hook is false until font metrics load, so you need to gate renders on it when using web fonts. It also doesn&#x27;t handle white-space: pre-wrap yet. Feedback welcome — especially if you&#x27;ve hit edge cases with font loading or non-Latin scripts.<p>GitHub: <a href="https:&#x2F;&#x2F;github.com&#x2F;ahmadparizaad&#x2F;pretext-studio-core" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;ahmadparizaad&#x2F;pretext-studio-core</a> — npm: @pretext-studio&#x2F;core