FEATURED · 精选文章

HyperFrames marker-highlight 组件全解:用 getTotalLength 描边实现手绘强调标记

发布时间 / 2026/9/10 1:56:00
来源 / 创域科博编辑部
栏目 / 资讯中心
HyperFrames marker-highlight 组件全解:用 getTotalLength 描边实现手绘强调标记 HyperFrames marker-highlight 组件全解用 getTotalLength 描边实现手绘强调标记【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes导读marker-highlight是 HyperFrames 官方 registry 中面向**语料强调corpus emphasis**场景的排版级运动原语一行展示文本先落入画面随后在指定 cue 时刻一支手绘马克笔以高亮、圆圈、下划线或涂鸦四种样式之一划过被强调的词。它由 registry-item.json 声明元数据、marker-highlight.html 承载完整实现全部机制浓缩为一个核心技巧——用 SVGgetTotalLength()测量路径长度后做 dash 描边动画。读完本文你将掌握该组件的全部 6 个变量、4 种样式、固定相位时间轴IN/DRAW/HOLD/OUT以及其在确定性渲染契约下的 seek-safe 设计原理并能在自己的 composition 中直接挂载与复用。一、组件定位一个语料强调单元在 HyperFrames 的组件体系里marker-highlight被明确归类为motion-primitive / typography / emphasis类型组件见 registry-item.json 的tags与jobs: [emphasize]family 为typographyprofile 为emphasis。它的行为模型非常克制一行展示文本稳定落位settle in然后一条手绘马克笔描边在 cue 时刻划过被强调的词。四种样式共享同一机制SVG 路径由getTotalLength的 dash tween 揭示。其默认时间预算为3.5s文本进入 → 弹性 HOLD完全静止直到画面切换→ 默认exit: none无退场动画锁定的版面一直保持到 cut。这种锁定排版lockup式设计非常适合讲解视频、产品演示、字幕强调等需要把观众视线精确引导到关键词上的场景。从源码结构看该组件被设计为弹性根elastic root#root不声明data-width/data-height而是填充宿主 clip 给定的任意盒子position: absolute; inset: 0通过 CSScontainer-type: size建立容器查询基准内部尺寸全部用cqw/cqh容器查询单位自适应。二、挂载协议把组件放进你的 composition2.1 标准挂载代码把以下 div 放入任意 composition 的 HTML 中即可挂载这是 README 中的官方挂载示例div classclip >div classclip>var matchIndex emphasis.length 0 ? text.toLowerCase().indexOf(emphasis.toLowerCase()) : -1;命中时把文本切为before matched after三段matched被包进带data-marker-style属性的.mh-em强调 spanSVG 标记.mh-markaria-hiddentrue置于其下方z-index: 0被强调文字本身.mh-em-textz-index: 1保持可读同时为整行设置aria-label保证辅助技术可读。四、四种标记样式路径数据与盒子几何所有标记路径都以固定 viewBox 手绘wobble抖动烘焙在控制点里、从不随机化。四种样式的完整路径数据见源码markerStyles表样式viewBox路径d节选strokeWidthopacityhighlight0 0 100 40M 3 24 C 22 20.5, 47 25.5, 68 22.5 ...260.5circle0 0 100 40M 22 7 C 58 1, 95 8, 97 20 ... C 4 10, 22 4, 52 4.52.81underline0 0 100 12M 2 7 C 20 4.5, 46 8.5, 66 6 ...4.51scribble0 0 100 40M 6 13 C 34 9.5, 66 11, 94 9 ... C 62 25, 28 27, 8 2950.65每种样式对应的 CSS 盒子相对于被强调词的 spanhighlightleft: -3%; top: 14%; width: 106%; height: 76%——盖在词后方的厚刷underlineleft: -2%; bottom: -14%; width: 105%; height: 22%且z-index: 2压在词下方但层级高于背景circleleft: -13%; top: -26%; width: 126%; height: 152%——宽松地环住整词scribbleleft: -2%; top: 12%; width: 104%; height: 76%。关键机制在于preserveAspectRationone作者路径在固定 viewBox 中被非等比拉伸进上述盒子。源码注释明确说明这是刻意保留的——SVG 作为替换元素若只做 inset 拉伸会退回其内在 viewBox 比例而preserveAspectRationone会连笔触一起变形这种各向异性的笔画失真正是手写笔尖横扫的质感来源。因此组件刻意不用non-scaling-stroke、也不用pathLength属性。五、核心机制getTotalLength dash tween四种样式共享同一个绘制机制这是本组件技术的精髓。实现分三步对应源码DRAW相位第一步测量真实路径长度。var length pathEl.getTotalLength(); pathEl.style.strokeDasharray String(length);getTotalLength()返回路径在拉伸后坐标系中的实际长度用它作为 dash 数组值保证描边动画覆盖整条路径与 viewBox 缩放无关。第二步隐藏到 cue 时刻。gsap.set(pathEl, { strokeDashoffset: length, opacity: 0 });初始strokeDashoffset length时整条虚线被推出可视区。源码注释提醒一个细节dashoffset 等于长度时圆头线帽stroke-linecap: round仍会在路径起点画出一个点所以额外把opacity设为 0直到绘制开始的那一帧才显示tl.set(pathEl, { opacity: marker.opacity }, drawAt);第三步dash 揭示。tl.fromTo( pathEl, { strokeDashoffset: length }, { strokeDashoffset: 0, duration: DRAW, ease: power2.inOut }, drawAt, );dashoffset 从length线性收敛到 0路径就像一支笔从起点扫到终点。power2.inOut缓动让起笔稍快、收笔渐缓接近真实运笔节奏。落位弹跳settle pop墨迹落地前被强调词会有一个轻微放大回弹作为落笔反馈tl.fromTo( emEl, { scale: 1 }, { scale: 1.045, duration: POP / 2, ease: power1.out, yoyo: true, repeat: 1 }, drawAt DRAW * 0.7, );即从draw_at起、在绘制进行到 70% 时触发放大到 1.045 再弹回整个弹跳在描边完成前结束。六、时间轴结构固定相位 弹性 HOLDREADME 声明3.5s authored, elastic HOLD源码中的重定时retime逻辑进一步展开了这个说法。时间轴由四段固定相位构成只有 HOLD 是唯一的弹性区间IN_BASE 0.55s 文本升起落位 DRAW_BASE 0.60s 马克笔描边 强调词落位弹跳 HOLD max(0, D - phases) 完全静止 OUT_BASE 0s (exit none) 或 0.45s (fade/up)关键规则如果 Dduration比固定相位之和更短各相位等比压缩scale duration / totalBase但 HOLD 与 OUT 的位置计算始终保证描边完整var scale duration totalBase ? duration / totalBase : 1; var IN IN_BASE * scale; var DRAW DRAW_BASE * scale; var POP POP_BASE * scale; var OUT OUT_BASE * scale; var OUT_START duration - OUT; // 描边与落位弹跳必须在任何退场开始前完成 drawAt Math.min(drawAt, Math.max(0, OUT_START - (DRAW POP)));draw_at的钳制公式min(draw_at, OUT_START - (DRAW POP))保证了即使作者把 cue 设得过晚描边也不会与退场重叠。各相位的具体动画INstage整行从opacity: 0, y: 6cqh以power3.out升起落位DRAW见第五节HOLD无任何动画完全静止直到 cut——这是lockup 保持语义的体现OUTfade淡出up淡出并上移-7cqh均为power2.in。注册的 timeline 是paused: true的 GSAP timeline且两个 dash 端点都显式给出strokeDashoffset: length → 0因此任何方向的 seek 都能直接落在正确状态无需先播放到该帧——这正是 determinism.mdx 与 frame-adapters.mdx 所要求的 seek-safe 行为渲染器逐帧seekFrame()动画从不播放。七、确定性设计无随机、无时钟README 的 Notes 强调该组件是Deterministic无随机性、dash 端点显式、双向 seek 安全。结合 determinism.mdx 的渲染规则可以逐条印证实现无未播种随机四条标记路径的控制点全部硬编码wobble is baked into the control points, never randomized也没有任何Math.random()调用无墙钟所有动画都在暂停的 GSAP timeline 上由渲染器 seek 驱动不存在Date.now()、requestAnimationFrame或定时器无渲染中途 fetch外部依赖仅 CDN 加载的 GSAPhttps://cdn.jsdelivr.net/npm/gsap3.14.2/dist/gsap.min.js在首帧前完成显式端点dash tween 的 from/to 值在构建时确定seek 到任意帧包括往回 seek都会得到精确一致的像素有限时长data-composition-duration3.5与根节点data-duration3.5声明已知终点。也就是说同一份 HTML 无论渲染多少次、无论预览还是最终出片每帧像素都一致——这是它能在 CI 与 AI 驱动的批量生产流程中被信任的前提。八、字体适配与换行策略组件对整行换行、强调短语不换行做了确定性处理强调词 span.mh-em设置了white-space: nowrap保证短语内部不折断整行.mh-text则可按容器宽度自然换行并居中字号通过按字符数拟合的公式计算var characters Math.max(1, Array.from(text).length); var fitted Math.max(4.2, Math.min(9.5, 185 / characters)); root.style.setProperty(--mh-font-size, min( fitted.toFixed(3) cqw, 16cqh));即字号随字数反比缩放185 / 字符数钳制在4.2cqw ~ 9.5cqw并叠加min(…, 16cqh)的高度上限——字符越多字越小避免长句溢出。注意Array.from(text).length按 Unicode 码点计数可正确处理 emoji 等多字节字符。排版属性font-weight: 600、line-height: 1.14、letter-spacing: -0.03em字体走var(--font-display, Inter, system-ui, sans-serif)主题 token背景var(--bg, #0b0c0e)、前景var(--fg, #f8fafc)。宿主可通过 CSS 变量覆盖整个视觉风格。九、实战建议与可继续探索的路径组合使用把marker-highlight与 HyperFrames 的 data attributes 能力结合用data-startprevious_clip_id 0.2做连续强调段落用 compositions 的嵌套机制在多个镜头复用同一组件。调整 cue 时序默认draw_at: 0.9配合IN_BASE 0.55s正好是文本落位后留出约 0.35s 停顿再起笔若想更紧凑可下调但注意它会受OUT_START - (DRAW POP)钳制。保持确定性自定义派生组件时坚持路径控制点硬编码 显式 dash 端点 paused timeline 无Math.random()四条铁律才能继续享受 确定性渲染 的全部保证。相关参考组件元数据见 registry-item.json挂载协议与变量机制见 compositions.mdx 与 variables.mdxGSAP timeline 适配见 frame-adapters.mdx可对比同类强调组件 vox-annotate 与 testimonial-proof-card 了解 emphasis 家族的多样化实现。适用前提说明marker-highlight是 registry 组件实际引用时应先通过项目工具链将组件源文件安装/拷贝到项目的compositions/目录registry-item.json 中target为compositions/components/marker-highlight.html再按本文第二节的挂载方式使用渲染需在 HyperFrames 运行时支持 GSAP seek 的浏览器运行时/engine下进行。【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED — 相关阅读

相关资讯

LATEST — 最新资讯

最新发布

TODAY — 本日精选

新闻

WEEKLY — 本周精选

新闻

MONTHLY — 本月精选

新闻