1实现原理 · 为什么它能做到
产出镜头:一张居中功能卡(圆形镂空框住点阵球)从右入场(0.25–1.80s)→ 带轻微上下浮动与纵深漂移的保持段 → 绕球心公转一整圈(4.97–5.97s,用 smoothstep)→ 向左退出(7.35–8.55s)。
One centred feature card with a circular cut-out framing a dot sphere. The card enters from the right (0.25–1.80 s), holds with a subtle bob and depth drift, orbits a full turn around the sphere's centre (smoothstep between 4.97 and 5.97 s), and exits left (7.35–8.55 s).
运动不是现场设计出来的,而是从已批准的 Blender rig 导出后在块内插值:相机路径与卡片 F-curve 按 30fps 烘焙成常量表,来源文件也写在数据里。
// Approved Blender motion, frame 1 = 0 seconds; generated from the existing saved-rig export. … fps: 30, … orbitFrames: [150, 180], … source: "orbit-card-motion-rig.blend",
因此变量只有 4 个(标题、描述、强调色、公转角度),且公转角度可给到 180°/720° 而不必动关键帧。
Title, description, accent and the orbit angle are variables; 180° and 720° work without touching keys.
结构上分三层:composition(109 行)只做挂载与时间线;场景在 assets/orbit-scene.js(WebGLRenderer 与几何);运动常量在 assets/orbit-motion.js(59 KB);且模块以参数接收变量,因为导入模块看不到本 composition 的 __hyperframes。
// Built per call from the variables the mounting module passes in: an imported // module only sees the page's __hyperframes, not its composition's.
坐标系做了显式换算:Blender X/Y/Z → Three X/Z/−Y,且 100 原始 CSS 像素 = 1 rig 单位,保证 2D 排版与 3D 场景对齐。
// Blender X/Y/Z -> Three X/Z/-Y. 100 original CSS pixels = one rig unit.
输入收敛:公转角度走有限数判断,强调色用六位 hex 正则校验、非法回默认,标题/描述做 String 兜底。
const number = (v, fallback) => (Number.isFinite(Number(v)) ? Number(v) : fallback); … const accent = /^#[0-9a-f]{6}$/i.test(V.feature1Accent) ? V.feature1Accent : "#4cc9ff";
seek 被夹在 [0,10];独立预览用 ?play(与 ?loop)查询参数驱动时间线。
timeline.totalTime(Math.max(0, Math.min(10, event.detail.time)), true); … if (query.has("play")) { timeline.repeat(query.has("loop") ? 999 : 0);
全本地:three 与 gsap 都是随包副本,字体 Archivo 亦以 @font-face 指向本地 ttf(regular/semibold,OFL),本块目录内没有任何 http(s) 引用。
font-family: Archivo; font-weight: 400; src: url("assets/archivo-regular.ttf");
2核心能力
3外部依赖
| 类型 | 依赖 |
|---|---|
| cli | HyperFrames 官方 CLI(add / render) |
| package | GSAP 3.14.2(随块本地副本) |
| package | three.js(随块本地副本)与场景模块 |
| package | Archivo 字体(regular/semibold,OFL) |
4风险提醒 风险提醒:蓝色 · 知晓即可
- 运动不可调(设计使然) — 相机与卡片轨迹被烘焙(orbit-motion.js 常量表),要改节奏只能改数据表或换块,不适合需要现场调编舞的项目。
- 单卡信息量有限 — 变量只支持一张卡(feature1*),多要点需复制块或改装 scene 模块。
- 文案长度受限 — 标题 max 28 字符、描述 max 110 字符(SKILL.md 变量表),超长文案需要改排版逻辑。
- 随包 three 体积 — three.module.min.js 与 three.core.min.js 合计约 1 MB 随块分发(对比 glass-shard-title 用内联打包产物减少文件数),对体量敏感的项目需评估。
5第二遍独立确认
- [ok] 变量数与声明一致性(frontmatter 自称 4 variables) — 脚本实测:SKILL.md 变量表 4 行、html data-composition-variables 解析出 4 项、frontmatter 写 4 —— 一致,为本批最小变量面。
- [ok] 「approved Blender motion」声称的真实性 — assets/orbit-motion.js 首行注释与字段(fps: 30、frameStart: 1、orbitFrames: [150,180]、source: "orbit-card-motion-rig.blend")逐字命中;运动确为烘焙数据而非现场函数。
- [ok] 零外链声称 — 对 orbit-card.html / orbit-scene.js / orbit-motion.js 做 http(s):// grep:零命中;脚本与字体全为 ./assets/ 相对路径。
- [ok] registry-item 文件清单 vs 盘上文件 — 声明 12 个文件(含两份许可与两枚字体)全部存在于盘上,无远端 url 兜底。
- [ok] 无随机/时钟依赖 — 本目录 grep Math.random / Date.now / requestAnimationFrame:零命中;运动全部来自常量表插值。
- [ok] 时长一致性 — registry-item duration 10、html data-duration 10、MOTION.duration 10、SKILL.md 标题行 10s —— 四处一致。
6结论
affb86a2ddee4335…d2f0bc7f34