SuperAPI AI 工具集

pretext-text-measurement

前端与建站

查看项目

更新于 10-15 14:31

技能介绍

用途

Pretext 是一个纯 JavaScript/TypeScript 库,用于快速、准确、无需 DOM 的多行文本测量与排版。它不调用 getBoundingClientRect 和 offsetHeight(这些会触发昂贵的布局重排),而是实现自己的测量逻辑,并以浏览器字体引擎作为基准真值。

主要能力

  • 无 DOM 测量段落高度:返回总像素高度与换行行数。
  • 手动逐行布局:获取固定宽度下的所有行,每行包含文本、宽度及起止游标。
  • 行统计:只返回行数与最大行宽,不产生字符串分配。
  • 自然宽度测量:文本不换行时的宽度,可用于按钮尺寸计算。
  • 可变宽度布局:支持文字环绕浮动图片等场景,逐行按不同宽度排版。
  • 迭代器 API:按固定宽度逐行产出文本与宽度。
  • 富文本内联流:支持混合字体、chip、@提及、内联代码片段等,可设置 break: 'never' 使元素保持原子性。
  • 富文本内联统计:返回行数与最大行宽。

使用方式

安装:

npm install @chenglou/pretext

核心概念:

  • prepare() / prepareWithSegments():一次性分析,规范化空白、切分文本、通过 canvas 测量。缓存并复用该结果。
  • layout() / layoutWithLines() 等:廉价热路径,对缓存宽度做纯算术。每次 resize 调用 layout(),而不是 prepare()。
  • 字体字符串格式:与 CanvasRenderingContext2D.font 相同,例如 '16px Inter'、'700 18px "Helvetica Neue"'。

选项:

{ whiteSpace?: 'normal' | 'pre-wrap' // 默认 'normal' wordBreak?: 'normal' | 'keep-all' // 默认 'normal' }

常用模式包括:虚拟列表行高预测量、二分搜索平衡文本宽度、resize 处理模式(文本/字体变化时才重新 prepare)、动态内容防布局偏移(先测量预留高度再插入 DOM)。

适用场景

  • 需要在插入 DOM 前测量文本高度以预留空间、防止布局偏移。
  • 虚拟化列表中预先计算每行高度。
  • 需要逐行手动渲染到 canvas。
  • 文字环绕浮动图片等可变宽度排版。
  • 混合字体、chip、@提及、内联代码的富文本内联流。
  • 需要 shrinkwrap 容器宽度(取最宽行)的场景。

限制

  • 服务端支持标注为“即将推出”,当前需要浏览器环境(canvas API)。
  • 字体字符串必须与 CSS font 简写完全一致(字重、样式、字号、字体族都重要)。
  • lineHeight 必须与 CSS line-height 的像素值一致。
  • 调用 prepare() 前字体必须已加载,可使用 document.fonts.ready 或 FontFace.load()。
  • prepare() 较慢,只应在文本或字体变化时调用;resize 时只调用 layout() 或等价函数。
  • CJK 文本换行不正确时可尝试 { wordBreak: 'keep-all' }。
  • 富文本内联项被错误断行时,为 chip、提及、徽章添加 break: 'never'。

API 速查

用途一(仅高度):

  • prepare(text, font, opts?):一次性分析,返回 PreparedText。
  • layout(prepared, maxWidth, lineHeight):返回 { height, lineCount }。

用途二(手动布局):

  • prepareWithSegments(text, font, opts?):一次性分析,返回 PreparedTextWithSegments。
  • layoutWithLines(prepared, maxWidth, lineHeight):返回 { height, lineCount, lines[] }。
  • walkLineRanges(prepared, maxWidth, onLine):逐行回调,无字符串分配。
  • measureLineStats(prepared, maxWidth):仅返回 { lineCount, maxLineWidth }。
  • measureNaturalWidth(prepared):文本不换行时的宽度。
  • layoutNextLineRange(prepared, cursor, maxWidth):迭代器,一次一个范围,可变宽度。
  • layoutNextLine(prepared, cursor, maxWidth):迭代器,一次一行加文本。
  • materializeLineRange(prepared, range):范围转 LayoutLine(含文本字符串)。

用途三(富文本内联):

  • prepareRichInline(items)
  • walkRichInlineLineRanges(prepared, width, callback)
  • materializeRichInlineLineRange(prepared, range)
  • measureRichInlineStats(prepared, containerWidth)