词元之母TOK.MOM - 平台充值汇率 1:1 即 1 人民币充值到账 1 美元,支持一个 Key 调用近 600+ 海内外模型,限时特价模型低至 1 折,欢迎上岸!
| 来源 | 内置(默认安装) |
| 路径 | skills/creative/pretext |
| 版本 | 1.0.0 |
| 作者 | Hermes Agent |
| 许可证 | MIT |
| 平台 | linux, macos, windows |
| 标签 | creative-coding, typography, pretext, ascii-art, canvas, generative, text-layout, kinetic-typography |
| 相关 skill | p5js, claude-design, excalidraw, architecture-diagram |
@chenglou/pretext 是由 Cheng Lou(React 核心团队、ReasonML、Midjourney)开发的 15KB 零依赖 TypeScript 库,用于无 DOM 多行文本测量与布局。它只做一件事:给定 (text, font, width),返回换行位置、每行宽度、每个字形(grapheme)的坐标以及总高度 —— 全部通过 canvas 测量完成,无需触发重排(reflow)。getBoundingClientRect 的情况下打包紧凑的多行 UI。pretext.cool 和 chenglou.me/pretext。ascii-art / ascii-video skill)p5jshello-orb-flow.html 模板只是起点。每个交付的演示都必须加入有意为之的色彩、动效、构图,以及一个用户没有要求但会欣赏的视觉细节。lorem ipsum。| 层级 | 工具 | 用途 |
|---|---|---|
| 核心 | @chenglou/pretext(通过 esm.sh CDN) | 文本测量 + 行布局 |
| 渲染 | HTML5 Canvas 2D | 字形渲染、逐帧合成 |
| 分割 | Intl.Segmenter(内置) | emoji / CJK / 组合字符的字形拆分 |
| 交互 | 原生 DOM 事件 | 鼠标 / 触摸 / 滚轮 —— 无框架 |
@0.0.6 —— 如演示行为异常,请在 npm 查看最新版本。font 和 letterSpacing 与 CSS 完全同步。 canvas 的 ctx.font 格式(如 "16px Inter"、"500 17px 'JetBrains Mono'")必须与渲染 CSS 一致,否则测量结果会产生偏差。measureLineStats(prepared, maxWidth) → { lineCount, maxLineWidth } —— 最宽的行,即多行紧缩包裹宽度。walkLineRanges(prepared, maxWidth, callback) —— 无字符串分配地遍历各行。在不需要字符内容时用于统计/物理计算。@chenglou/pretext/rich-inline —— 同一系统,但支持混合字体 / 标签 / 提及的段落。从子路径导入。references/patterns.md)归纳为几种强力模式。选一种进行变奏 —— 除非被要求,否则不要发明新类别。| 模式 | 核心 API | 示例创意 |
|---|---|---|
| 绕障重排 | layoutNextLineRange + 逐行宽度函数 | 编辑排版段落,绕拖拽光标精灵分开 |
| 文字即几何游戏 | layoutWithLines + 逐行碰撞矩形 | 每块砖都是一个测量过的单词的打砖块游戏 |
| 碎裂 / 粒子 | walkLineRanges → 每字形 (x,y) → 物理 | 点击时句子炸裂成字母 |
| ASCII 障碍排版 | layoutNextLineRange + 逐行障碍区间测量 | 位图 ASCII logo、形态变换,以及可拖拽的线框物体,使文字绕其实际几何形状展开 |
| 编辑多栏 | 每栏 layoutNextLineRange + 共享游标 | 带引用块的动态杂志版面 |
| 动态排版 | layoutWithLines + 逐行随时间变换 | 星球大战字幕滚动、波浪、弹跳、故障效果 |
| 多行紧缩包裹 | measureLineStats | 自动适配最紧凑容器的引用卡片 |
templates/donut-orbit.html 和 templates/hello-orb-flow.html 中可运行的单文件起始模板。templates/hello-orb-flow.html —— 文字绕移动球体重排(绕障重排模式)templates/donut-orbit.html —— 进阶示例:测量 ASCII logo 障碍物、可拖拽线框球体/立方体、变形形状场、可选 DOM 文字及仅开发模式控件write_file 将新 .html 写入 /tmp/ 或用户工作区。cd <dir-with-html> && python3 -m http.server 8765
# then open http://localhost:8765/<file>.htmlprepareWithSegments 传入错误的字体字符串,pretext 会抛出异常;Intl.Segmenter 在所有现代浏览器中均可用。prepare() / prepareWithSegments() 是开销较大的调用。每个文字+字体组合只调用一次,缓存句柄。layout() / layoutWithLines() —— 绝不重新 prepare。layoutNextLineRange 对普通长度的段落来说足够在 60fps 下每帧执行。Uint8Array / 类型化数组),从单元格或投影几何体推导每行障碍区间,合并区间,再将这些区间传入 layoutNextLineRange 后绘制文字。ctx.font 设置出人意料地慢;若字体在帧内不变,每帧只设置一次,而非每次 fillText 调用都设置。ctx.font = "16px Inter" 用于测量,但 CSS 写的是 font-family: Inter, sans-serif; font-size: 16px。如果 Inter 加载成功则没问题。若 Inter 404,CSS 会回退到 sans-serif,测量结果偏差 5-20%。始终 preload 字体,或使用 web 安全字体族。layout* 是廉价的。每帧调用 prepare 会严重拖慢性能。将 prepared 句柄保存在模块作用域中。Intl.Segmenter 拆分字形。 Emoji、组合字符、CJK —— "é".split("") 会给出两个字符。在采样单个可见字形时,使用 new Intl.Segmenter(undefined, { granularity: "grapheme" })。break: 'never' 标签缺少 extraWidth。 在 rich-inline 中,若对原子标签/提及使用 break: 'never',还必须提供 extraWidth 用于标签内边距 —— 否则标签外框会溢出容器。unpkg 使用 @chenglou/pretext 时遇到 TypeScript 专属入口。 使用 esm.sh —— 它会自动将 TS 导出编译为浏览器可用的 ESM。unpkg 会 404 或返回原始 TS。font-family 回退到了 monospace。通过 DevTools 验证实际渲染字体。y += lineHeight; continue;),而非向 layoutNextLineRange 传入极小的 maxWidth —— pretext 会返回单字形行,看起来很破碎。.html 文件 —— 双击或 python3 -m http.server 即可打开@chenglou/pretext 通过 esm.sh 导入并锁定版本prepare 的字体字符串与 CSS 字体完全一致prepare() / prepareWithSegments() 只调用一次,不在每帧调用python3 -m http.server 本地测试,确认无控制台报错github.com/rinesh/pretext-breakergithub.com/shinichimochizuki/tetris-pretextgithub.com/qtakmalay/PreTextExperimentsgithub.com/somnai-dreams/pretext-demosgithub.com/frmlinn/bad-apple-pretextgithub.com/dokobot/pretext-demogithub.com/SmisLee/alarmy-pretext-demo