HyperFrames halftone-dissolve 组件:基于种子阈值场的点阵溶解转场原理与实战
【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes
HyperFrames 是"Write HTML, Render video"的开放视频框架,它的 registry 中收录了大量可复用的 HTML 视频组件,而halftone-dissolve正是其中一款面向转场/纹理场景的过渡图元:场景 A 通过一个不断扩张的半调(halftone)点阵"溶解"进场景 B,网点以"最小优先"的顺序在固定错排网格上以强调色弹出,随后每个网点开启一扇通向 B 的圆形窗口,直至窗口合并、B 完全取代 A。读完本文,你将掌握该组件的安装、双场景插槽装配、五个配置变量的取值语义,以及它如何借助固定种子 LCG 阈值表和单一进度补间实现逐帧可复现的确定性渲染。
核心文档位于 registry/components/halftone-dissolve/README.md,完整实现见同目录下的 halftone-dissolve.html,本文结合源码逐行展开。
效果与设计目标
从视觉呈现来看,这一转场是一个"墨水扩散"过程:
- 网点先以强调色(accent ink)出现在固定网格格点上,按阈值顺序最小优先生长;
- 每个墨点"领先一拍"地开启一扇窗口,露出其后的场景 B——即每个格点先闪现强调色,再被 B 填满;
- 窗口最终合并覆盖全屏,
clip-path释放,B 完全静止展示。
每个网点的半径是**(网格位置, 进度 p)的纯函数**,由种子阈值表(seeded threshold map)驱动,方向枚举(direction)决定阈值的读取顺序。该组件默认内置 3.5s 时长、在 B 上以"弹性 HOLD"结尾(永不做 time-scale)。
概念澄清:这里的A/B 场景都是插槽(slot),不是组件内固定的图片素材。调用方只需要在宿主页面任意位置放两个惰性
<template>,运行时会把内容搬进场景层;缺省时组件会用纯设计令牌绘制的"字母牌"占位(A 用中性色,B 用强调色),这一点在源码注释(halftone-dissolve.html 第 11-20 行)和 registry-item.json 的type: "hyperframes:component"、family: "transitions"、profile: "texture"元数据中均可印证。
组件元数据还给出了它的定位:jobs: ["bridge"](桥接两段画面),tags为motion-primitive / transition / texture / halftone / dissolve,并声明了唯一同步点syncPoints: [{ id: "dissolve", phase: "in", offset: 1.1 }],即溶解在 1.1s 处触发——这部分与运行时的事件对齐(如为音效打点)直接相关。
安装与目录产物
该组件通过 HyperFrames CLI 的 add 子命令安装:
npx hyperframes add halftone-dissolveCLI 的用法表在 docs/developers/cli.mdx 中登记为 "Add a Catalog item:npx hyperframes add <name>"。命令会写入一个文件:
compositions/components/halftone-dissolve.html在仓库内,组件源文件位于 registry/components/halftone-dissolve/halftone-dissolve.html,随附的 registry-item.json 中files[0]记录了发布目标路径compositions/components/halftone-dissolve.html,与 CLI 行为一致。
安装后可把它粘贴进自己的 composition——组件本身没有自己的尺寸和时长,二者都取自你所粘贴进的 composition。目录页 docs/catalog/components/halftone-dissolve.mdx 中同样说明了这一用法,并指出"每个变量都有默认值,不设置任何参数也能原样工作"。
在宿主页面中挂载
READ ME 给出的最小挂载结构是把组件当作宿主页面中的一个.clip元素:
<div class="clip" ><template><template><div >var duration = ...parseFloat(root.dataset.duration || "3.5"); var OUT = exit === "none" ? 0 : 0.45; // 可选离场 0.45s var DISSOLVE = Math.min(1.3, Math.max(0.4, duration - OUT - 0.6)); // 溶解恒 ≤1.3s var maxAt = Math.max(0.2, duration - DISSOLVE - OUT - 0.05); var dissolveAt = num(vars.dissolve_at, 1.1, 0.2, maxAt); // 钳制到 maxAt 内 var OUT_START = duration - OUT;实际时间线由三条 GSAP 结构组成:
- 一条锚点补间
tl.to({t:0},{t:1, duration, ease:"none"},0)横跨整个创作时长,目的是让onUpdate画图在 [0, D] 内任何一次"事件式 seek"都被触发,同时让 HOLD 段保持tl.time()诚实; - 一条进度补间
tl.fromTo(P, {p:0},{p:1, duration:DISSOLVE, ease:"power1.inOut"}, dissolveAt),这是溶解本体的唯一驱动——power1.inOut让前锋两端都不仓促(最小优先地弹出、不勉强的合并); - HOLD 不写任何补间;仅当
exit非 none 时,在OUT_START追加 0.45s 的power2.in离场(up同时上移-4cqh与淡出,fade仅淡出)。
整条时间线paused: true,最后tl.seek(0); paint()后注册到window.__timelines["halftone-dissolve"],等待帧适配器逐帧 seek——这正符合 HyperFrames 的确定性模型(见下节)。
确定性渲染原理
README 的 Determinism 一节是理解该组件工程价值的关键:
网格与其阈值表在构建时用固定 LCG 种子只计算一次;一个普通对象的进度补间喂给唯一一个画师,该画师从零重绘墨点画布、并重建 B 的
clip-path字符串——全部是 progress 的纯函数。因此任意顺序、任意方向的事件式 seek 都会落在完全相同的帧上。栅格与 clip-path 的基准是挂载时测量一次的宿主盒子。
映射到源码(halftone-dissolve.html):
- 固定种子 LCG:
var state = 0x4a17f03d;随后state = (Math.imul(1664525, state) + 1013904223) >>> 0;(第 273-277 行)。这是标准的 Numerical Recipes 线性同余生成器参数,种子是硬编码常量,保证每次运行产生同一张抖动/散列序列; - 只在构建时计算一次:网格生成在一个 IIFE 中完成,阈值
th由方向决定的基础量(center用到中心的归一化距离、noise直接取next()、否则用x/cssW)叠加种子抖动((next()-0.5)*0.22)并乘以0.62归一化后写入点表; - 半径是 (位置, 进度) 的纯函数:
windowRadius(dot,p) = R_MAX * smooth(clamp01((p - dot.th)/0.38)),inkRadius则把进度前移0.07,实现"墨点领先窗口一拍"(第 310-315 行);smooth()即三次平滑v²(3-2v); - 单一画师:
onUpdate: paint每帧清空墨点画布、按点表填充墨点圆,并逐点拼出M..A..A..Z的 clip-pathpath()字符串赋给.htd-scene-b(第 330-382 行)。lastClip缓存仅用于跳过字符串相同的样式写入,绝不用于跳过变化帧的重绘; - 没有
Math.random()时序依赖:所有随机性来自种子 LCG;渲染逐帧 seek、不"播放",因此无论 seek 方向与顺序如何,帧内容都确定。
这一节也是整个框架"Same input, identical output"保证的一个实例化:框架级约定(无墙钟、无未播种随机、无渲染中途 fetch、帧锁定 fps/宽/高)记录在 docs/concepts/determinism.mdx,每次渲染逐帧seekFrame(frame)、GSAP 时间线一律暂停并 seek(见 docs/concepts/frame-adapters.mdx)。对 halftone-dissolve 而言,这意味着它的所有伪随机视觉都由0x4a17f03d这一个种子决定——任何对"抖动排布"的视觉调整,本质上都要回到种子与dot_size网格密度这两处。
其他网格与分辨率要点
- 经典半调错排:
x = (c + (r%2===0 ? 0.25 : 0.75)) * cell(第 282 行),交替行错开半格,正是经典 halftone 交错的网格形态;行数/列数各多算 1-2 个以保证边界无洞。 - 最大半径:
R_MAX = cell * 0.78,使相邻圆在满覆盖时互相重叠,从而实现窗口合并后的无缝全屏。 - 栅格基准与 DPR:画布物理分辨率 = CSS 尺寸 ×
min(2, max(1, devicePixelRatio)),cssW/cssH与 clip-path 的坐标系统一来自挂载时一次性测量的getBoundingClientRect()(缺省回退 640×360),避免逐帧测量导致的不确定性。
快速对照:仓库文件速查
| 文件(仓库根相对路径) | 作用 |
|---|---|
| registry/components/halftone-dissolve/README.md | 组件权威说明:挂载、插槽、变量、编排、确定性 |
| registry/components/halftone-dissolve/halftone-dissolve.html | 完整实现:CSS、插槽解析、LCG 点表、GSAP 时间线、单画师 |
| registry/components/halftone-dissolve/demo.html | 1920×1080 浅色主题宿主,示范非默认变量 + 双插槽装配 |
| registry/components/halftone-dissolve/registry-item.json | 目录元数据:标签、family/profile、同步点、变量 schema |
| docs/catalog/components/halftone-dissolve.mdx | 站点目录页:安装命令、变量表、完整源码展示 |
| docs/concepts/determinism.mdx | 框架级确定性渲染规则背景 |
| docs/developers/cli.mdx | npx hyperframes add等 CLI 用法 |
小结
halftone-dissolve演示了 HyperFrames 组件设计的一整套惯用法:无自持尺寸与时长、内容走宿主插槽、外观全部消费设计令牌、时间线固定段 + 弹性 HOLD、随机性收敛到单一固定种子。安装后你只需要做三件事——把它的 HTML 内容并入 composition、按需在元素上覆盖dot_size / direction / dissolve_at / accent / exit、再在宿主里给出 A/B 两个场景模板——即可获得一段对逐帧渲染完全确定的半调点阵溶解转场;若在 dissolve 触发的 1.1s 时间点有音效需求,可直接对齐它声明的dissolve同步点。
【免费下载链接】hyperframesWrite HTML. Render video. Built for agents.项目地址: https://gitcode.com/GitHub_Trending/hy/hyperframes
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考