首页
/ OpenMontage HyperFrames HTML-in-Canvas 实战指南:把任意 HTML/CSS 实时捕获为 GPU 纹理并叠加 WebGL 视觉特效

OpenMontage HyperFrames HTML-in-Canvas 实战指南:把任意 HTML/CSS 实时捕获为 GPU 纹理并叠加 WebGL 视觉特效

2026-09-07 20:32:49作者:柯茵沙

本篇指南围绕 OpenMontage 仓库中 HyperFrames 动画技能集的核心适配器 html-in-canvas-patterns.md 展开,系统讲解「把实时 DOM 渲染为 GPU 纹理,再交由 Three.js / WebGL2 / GLSL 后期处理呈现」的完整套路。读完你将掌握:一份可复用的双 Canvas 样板代码、5 类开箱效果与 5 段可直接改用的 GLSL 后处理片段、任意自定义 Shader 效果的四步接入方法,以及「何时用 HTML-in-Canvas、何时退回标准 GSAP」的取舍依据。

背景:HTML-in-Canvas 在 HyperFrames 中的定位

HyperFrames 是一种「从 HTML 渲染视频」的确定性动画运行时:一部作品本质是一个 HTML 文件,DOM 用 data-* 属性声明时间,动画由一条 paused GSAP 时间线驱动,渲染引擎按时间线逐帧 seek、截图、编码成 MP4(hyperframes-core 组合契约)。在 OpenMontage 仓库中,HyperFrames 被封装为一套 .agents/skills/hyperframes-* 分层技能(核心入口动画技能总览),并作为与 Remotion 并列的 render_runtime 选项接入各生产管线(见 OpenMontage 侧的 HyperFrames 桥接指南)。

在整套动画技能里,adapters/html-in-canvas-patterns.md 被定位为 HyperFrames 最强的一种视觉能力:它借助 Chrome 的 layoutSubtree + drawElementImage 实验 API,把页面上任何一段「活的」HTML/CSS(文字、图片、卡片、仪表盘……)直接光栅化进 canvas 纹理,随后无论塞进 WebGL 片元着色器、贴上 Three.js 3D 平面、还是走 EffectComposer 后期链,都是对同一份「像素级精确的实时 UI」做艺术化处理。

但技能文档明确强调一条纪律:一段视频只该有 1~3 个 hero beat 使用它,其余 beat 继续用普通 GSAP。原因不只是性能,更在于叙事——「平面 GSAP beat」与「HTML-in-Canvas 电影级 beat」之间的落差本身,就是视觉叙事的一部分。这与 hyperframes-animation/techniques.md 中「capturing live HTML/CSS as a GPU texture 是独立的重型能力,只用于 1–3 个 hero beat」的指引一致,也与该技能默认的「先选 2–4 条原子规则拼时间线」工作流形成互补(SKILL.md)。

核心样板:每种 HTML-in-Canvas 效果的共同骨架

无论最终呈现是 3D 旋转、液体表面还是门户传送,结构都只有一套。先学会它,任何效果都能基于它改写。

第一步:源画布与输出画布(HTML)

源画布 <canvas id="hic-source"> 带有 layoutsubtree 属性,里面套一个确定尺寸的内容容器 <div id="hic-content">(1920×1080),你的全部 HTML 内容写在这里;整个源画布绝对定位并设 opacity: 0,它只负责「被截图」,不负责「被看见」。真正可见的是第二块输出画布 hic-output

<!-- 1. Source HTML — your content goes inside a layoutsubtree canvas -->
<canvas
  id="hic-source"
  layoutsubtree
  width="1920"
  height="1080"
  style="position:absolute;inset:0;opacity:0;"
>
  <div id="hic-content" style="width:1920px;height:1080px;">
    <!-- YOUR HTML CONTENT HERE — text, images, cards, dashboards, anything -->
  </div>
</canvas>

<!-- 2. Render target — the visible canvas that shows the effect -->
<canvas id="hic-output" width="1920" height="1080" style="position:absolute;inset:0;"></canvas>

第二步:特性检测——永远检查、永远兜底(JS)

drawElementImage 是实验能力,未启用 Chrome flag 的浏览器里根本不存在。因此每一份组合都要先探测:先检查 canvas 是否支持 layoutSubtree 属性,再取 2D 上下文并确认 drawElementImage 是函数。

// 3. Feature detection — always check, always provide fallback
function isHiCSupported() {
  var tc = document.createElement("canvas");
  if (!("layoutSubtree" in tc)) return false;
  tc.setAttribute("layoutsubtree", "");
  var ctx = tc.getContext("2d");
  return ctx && typeof ctx.drawElementImage === "function";
}
var apiOk = isHiCSupported();

第三步:逐帧捕获函数(JS)

捕获逻辑只有一行——把 hic-contentdrawElementImage 画进源画布的 2D 上下文。它必须在动画的每一帧都被调用,因为你要捕获的是「当前时刻的 DOM 状态」。

// 4. Capture function — call this every frame in onUpdate
var capCanvas = document.getElementById("hic-source");
var capCtx = capCanvas.getContext("2d");
function captureContent() {
  if (apiOk) {
    capCtx.drawElementImage(document.getElementById("hic-content"), 0, 0, 1920, 1080);
  }
}

第四步:用 GSAP 时间线驱动——每帧「先捕获、再渲染」(JS)

HyperFrames 的一切动画都收敛在一条 paused GSAP 时间线(文档中的 tl)上。做法是 tweens 一个普通对象代理 proxy,在 onUpdate 回调里同步执行「捕获内容 + 渲染你的效果」:

// 5. Drive from GSAP timeline — capture + render every frame
tl.to(
  proxy,
  {
    /* your animation properties */
    duration: BEAT_DURATION,
    ease: "sine.inOut",
    onUpdate: function () {
      captureContent();
      // render your effect here (Three.js or WebGL2)
    },
  },
  0,
);

值得注意的是:onUpdate 回调与 tl.call() 在这套确定性运行时里是被官方允许、甚至被依赖的——canvas/WebGL 渲染与逐字打字模式都靠它们驱动(第 484 行附近关于 linter 的说明)。真正被禁止的是 Math.randomDate.nowrequestAnimationFramerepeat: -1 这类会破坏「同一时间线每一帧画面可复现」的行为。

兜底策略:当 drawElementImage 不可用(例如未加 Chrome flag 的普通预览环境)时,用纯色占位或 Canvas 2D 文字代替内容。HyperFrames 渲染引擎在正式出片时会自动加上对应 flag,因此最终视频里效果一定生效——预览环境的兜底只影响本地调试观感,不影响产物。完整的兜底实现可以参考 liquid-glass 相关 block(实现细节见下文「效果目录」第 4/5 节的 registry 指引)。

与 WebGPU 类效果的环境差异:同属本仓库的 TypeGPU/WebGPU 适配器文档 typegpu.md 进一步说明,渲染引擎向 Chrome 启动参数自动追加 --enable-unsafe-webgpu--enable-features=CanvasDrawElement;但原版 Chromium 与随附的 headless-shell 无法同时支持 WebGPU + drawElementImage。需要该组合(如 ios26-liquid-glassvfx-liquid-glass 等 block)时,应先把 PRODUCER_HEADLESS_SHELL_PATH 指向 Brave 或 Chrome canary 的可执行文件,再执行 npx hyperframes render / preview。纯 TypeGPU 图层(不涉及 HTML 纹理)则可以直接在 headless-shell 里工作。

效果目录 1:3D 旋转 + Bloom 辉光(Three.js)

观感:内容悬浮在 3D 空间中缓慢旋转,亮边带着电影级辉光——像一件产品截图陈列在黑暗放映厅里。 适用场景:Hero 产品展示、功能揭晓、需要高级感的 CTA。 关键 Three.js 组件PlaneGeometry + CanvasTexture + EffectComposer + UnrealBloomPass

在样板代码之后追加:

// After the boilerplate above, add:
var scene3d = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(45, 1920 / 1080, 0.1, 100);
camera.position.set(0, 0, 4);

var renderer = new THREE.WebGLRenderer({
  canvas: document.getElementById("hic-output"),
  antialias: true,
  alpha: true,
});
renderer.setSize(1920, 1080);

var texture = new THREE.CanvasTexture(capCanvas);
var mesh = new THREE.Mesh(
  new THREE.PlaneGeometry(3.6, 2.2),
  new THREE.MeshBasicMaterial({ map: texture }),
);
scene3d.add(mesh);

// Post-processing: bloom for cinematic glow.
// EffectComposer / RenderPass / UnrealBloomPass are ES-module named imports
// (see the import block below) — they're NOT properties of THREE in modern
// versions. Three.js r150+ removed the UMD `examples/js/` globals.
var composer = new EffectComposer(renderer);
composer.addPass(new RenderPass(scene3d, camera));
composer.addPass(new UnrealBloomPass(new THREE.Vector2(1920, 1080), 0.3, 0.4, 0.85));

var proxy = { rotY: -0.12, zoom: 4.2 };
tl.to(
  proxy,
  {
    rotY: 0.12,
    zoom: 3.6,
    duration: BEAT_DURATION,
    ease: "sine.inOut",
    onUpdate: function () {
      captureContent();
      texture.needsUpdate = true;
      mesh.rotation.y = proxy.rotY;
      camera.position.z = proxy.zoom;
      composer.render();
    },
  },
  0,
);

两个关键细节:

  • 捕获画布被包成 THREE.CanvasTexturetexture.needsUpdate = true 必须放在每帧更新里,否则 GPU 侧的纹理不会随捕获内容刷新;
  • 相机拉近/旋转由 GSAP 代理 rotYzoom 驱动,动画曲线集中在时间线一处管理。

用 ESM 加载 Three.js 与后期处理(需要 type="module" 脚本)

<script type="module">
  import * as THREE from "https://cdn.jsdelivr.net/npm/three@0.181.2/+esm";
  import { EffectComposer } from "https://cdn.jsdelivr.net/npm/three@0.181.2/examples/jsm/postprocessing/EffectComposer.js";
  import { RenderPass } from "https://cdn.jsdelivr.net/npm/three@0.181.2/examples/jsm/postprocessing/RenderPass.js";
  import { ShaderPass } from "https://cdn.jsdelivr.net/npm/three@0.181.2/examples/jsm/postprocessing/ShaderPass.js";
  import { UnrealBloomPass } from "https://cdn.jsdelivr.net/npm/three@0.181.2/examples/jsm/postprocessing/UnrealBloomPass.js";
  // ... rest of composition code using these imports
</script>

版本选择要特别留意:Three.js r150+ 已移除 UMD 形态的 examples/js/ 全局变量examples/js/ 路径更是在 r152 被彻底删除。所以请坚持用 ESM 的 examples/jsm/ 路径搭配 three@0.181.2——这也是 HyperFrames Three.js 适配器锁定的版本(仓库内 three 适配器能力清单 均记录同一加载地址)。

效果目录 2:磁性光标扭曲(原生 WebGL2)

观感:内容朝一个移动中的点弯曲、被「磁吸」,畸变处出现 RGB 通道分离的色差。 适用场景:需要交互感的产品演示、光标跟随的「请看这个功能」时刻。 关键技术:纯 WebGL2 的自定义片元着色器,实现高斯形 warp + 色差分裂,不需要 Three.js。

// WebGL2 setup
var gl = document.getElementById("hic-output").getContext("webgl2", {
  alpha: false,
  preserveDrawingBuffer: true,
});

// Vertex shader — full-screen quad
var VS = `#version 300 es
in vec2 a_pos;
out vec2 v_uv;
void main() {
  v_uv = a_pos * 0.5 + 0.5;
  gl_Position = vec4(a_pos, 0.0, 1.0);
}`;

// Fragment shader — magnetic warp + chromatic aberration
var FS = `#version 300 es
precision highp float;
in vec2 v_uv;
out vec4 fragColor;
uniform sampler2D u_tex;
uniform vec2 u_cursor;   // cursor position (0-1)
uniform float u_strength; // warp strength (0-1)

void main() {
  vec2 uv = v_uv;
  vec2 delta = uv - u_cursor;
  float dist = length(delta);
  float warp = u_strength * exp(-dist * dist * 8.0);
  vec2 warped = uv - delta * warp * 0.3;

  // Chromatic aberration at distortion site
  float aberration = warp * 0.008;
  float r = texture(u_tex, warped + vec2(aberration, 0.0)).r;
  float g = texture(u_tex, warped).g;
  float b = texture(u_tex, warped - vec2(aberration, 0.0)).b;
  fragColor = vec4(r, g, b, 1.0);
}`;

// Compile, link, setup quad geometry, upload texture...
// (See registry/blocks/vfx-magnetic/vfx-magnetic.html for complete implementation)

// Drive cursor position from GSAP
var proxy = { cx: 0.2, cy: 0.5, strength: 0.0 };
tl.to(
  proxy,
  {
    cx: 0.8,
    cy: 0.4,
    strength: 1.0,
    duration: BEAT_DURATION,
    ease: "power2.inOut",
    onUpdate: function () {
      captureContent();
      // Upload texture, set uniforms, draw
      gl.uniform2f(cursorLoc, proxy.cx, proxy.cy);
      gl.uniform1f(strengthLoc, proxy.strength);
      gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
    },
  },
  0,
);

这套代码展示了 HTML-in-Canvas 的另一种形态:着色器不是包在 3D 场景里,而是直接消费纹理。其中顶点着色器输出一个覆盖全屏的四边形,v_uv = a_pos * 0.5 + 0.5 把裁剪坐标 [-1,1] 换算为纹理坐标 [0,1];gl.getContext("webgl2", { preserveDrawingBuffer: true }) 保证逐帧捕获时绘制缓冲不丢帧。

效果目录 3:粉碎 / 碎片爆炸(Three.js)

观感:内容碎成几何碎片向四周飞散,露出后方内容。 适用场景:戏剧性转场、「挣脱束缚」时刻、张力释放。 关键技术:用 BufferGeometry 把源纹理细分出三角形网格碎片,再用 GSAP 逐片驱动位置与旋转。

完整 1156 行实现请研究注册表里的 registry/blocks/vfx-shatter/vfx-shatter.html(本仓库中 vfx-shatter 作为可安装的 VFX registry block 存在,见 registry 发现文档 中 "VFX (6)" 分类表)。核心思路如下:

// 1. Capture content to texture (same boilerplate)
// Seeded PRNG for determinism — Math.random() is banned
function mulberry32(seed) {
  return function () {
    seed |= 0;
    seed = (seed + 0x6d2b79f5) | 0;
    var t = Math.imul(seed ^ (seed >>> 15), 1 | seed);
    t ^= t + Math.imul(t ^ (t >>> 7), 61 | t);
    return ((t ^ (t >>> 14)) >>> 0) / 4294967296;
  };
}
var rng = mulberry32(42);

// 2. Create N triangle fragments from the texture
var fragments = [];
for (var i = 0; i < NUM_FRAGMENTS; i++) {
  var geom = new THREE.BufferGeometry();
  var mesh = new THREE.Mesh(geom, new THREE.MeshBasicMaterial({ map: texture }));
  scene3d.add(mesh);
  fragments.push({ mesh: mesh, targetPos: randomExplosionVector(rng), delay: rng() * 0.5 });
}

// 3. Animate: first hold still, then EXPLODE
tl.to({}, { duration: holdTime }, 0);
fragments.forEach(function (frag) {
  tl.to(
    frag.mesh.position,
    {
      x: frag.targetPos.x,
      y: frag.targetPos.y,
      z: frag.targetPos.z,
      duration: 0.8,
      ease: "power3.in",
    },
    holdTime + frag.delay,
  );
  tl.to(
    frag.mesh.rotation,
    { x: rng() * 4, y: rng() * 4, duration: 0.8, ease: "power2.in" },
    holdTime + frag.delay,
  );
});

确定性是这个效果的重中之重Math.random() 在 HyperFrames 中是被禁用的(linter 会直接拦截),因此这里引入 mulberry32(42) 种子化伪随机数生成器,并用固定种子产生爆炸向量与延迟——同一时间线、同一帧,画面永远可复现,这正是 技能硬性约束 中「seeded PRNG、禁 Math.random」规则在视觉特效里的直接应用。时间编排上先让碎片 holdTime 原地静止,再按各自 delay 逐个以 power3.in 加速炸出。

效果目录 4:液体 / 流体表面(Three.js)

观感:内容浮在一片带实时波动动力学的涟漪液面上;也可以让内容本身就是液面,如水般起伏。 适用场景:有机感/高级感、氛围背景、「活的」产品展示。 关键技术:细分 PlaneGeometry + 顶点着色器里的噪声函数做顶点位移。

完整 1244 行实现参考 registry/blocks/vfx-liquid-background/vfx-liquid-background.html(同样作为 registry block 存在)。核心思路:

// Custom vertex shader with wave displacement
var vertexShader = `
  varying vec2 vUv;
  uniform float u_time;
  void main() {
    vUv = uv;
    vec3 pos = position;
    // Sine wave displacement
    pos.z += sin(pos.x * 3.0 + u_time * 2.0) * 0.15;
    pos.z += cos(pos.y * 2.5 + u_time * 1.5) * 0.1;
    gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
  }
`;

var mesh = new THREE.Mesh(
  new THREE.PlaneGeometry(4, 3, 64, 64), // heavily subdivided for smooth waves
  new THREE.ShaderMaterial({
    vertexShader: vertexShader,
    fragmentShader: `varying vec2 vUv; uniform sampler2D u_tex;
      void main() { gl_FragColor = texture2D(u_tex, vUv); }`,
    uniforms: {
      u_tex: { value: texture },
      u_time: { value: 0 },
    },
  }),
);

要点解析:

  • PlaneGeometry(4, 3, 64, 64) 的 64×64 高度细分是为了给波提供足够网格顶点,细分不足会出现多边形化折痕;
  • 波形由两路不同频率/相位的三角波叠加(sin(x*3.0 + t*2.0)cos(y*2.5 + t*1.5)),各自独立振幅(0.15 与 0.1),叠加后更接近自然的复合波;
  • u_time 这个 uniform 需由外层 GSAP onUpdate 驱动(textureu_time 都在 uniforms 中声明,别忘把捕获纹理作为 u_tex 传入)。

效果目录 5:传送门 / 维度揭示(Three.js)

观感:一个发光的圆形传送门缓缓打开,内容从另一个维度穿门而出。 适用场景:产品揭晓、「进入应用内部」时刻、Hero 功能导入。 实现方式:完整 863 行实现参考 registry/blocks/vfx-portal/vfx-portal.html(registry block vfx-portal,见 registry 发现文档)。它同样建立在核心样板之上——捕获 HTML 内容、采样为纹理、套用圆形 SDF 掩膜与辉光着色器。

更多可自建效果:五个单函数 GLSL 后处理模板

以下效果不在官方 VFX block 里,需要你自己基于核心样板 + 一段自定义片元着色器构建。每个效果本质上都是「应用到已捕获纹理上的一个 GLSL 函数」。

效果 6:噪点溶解(Noise Dissolve)

内容溶解为噪点颗粒、露出后方。适合转场。u_progress 0.0 = 完全可见,1.0 = 完全溶解,溶解边界带橙色辉光边缘:

// Fragment shader — noise-based dissolve
uniform float u_progress; // 0.0 = fully visible, 1.0 = fully dissolved
uniform sampler2D u_tex;

float hash(vec2 p) {
  return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
}

void main() {
  vec2 uv = v_uv;
  float noise = hash(uv * 50.0);
  float threshold = u_progress;
  if (noise < threshold) {
    // Edge glow at the dissolve boundary
    float edge = smoothstep(threshold - 0.05, threshold, noise);
    fragColor = vec4(1.0, 0.6, 0.2, 1.0) * (1.0 - edge); // orange edge glow
  } else {
    fragColor = texture(u_tex, uv);
  }
}

效果 7:全息 / 虹彩(Holographic / Iridescent)

内容覆盖一层随时间漂移的彩虹式全息光晕,未来感强。核心是用位置+时间的角度合成三路相位差 120° 的正弦值形成 RGB:

uniform float u_time;
uniform sampler2D u_tex;

void main() {
  vec4 color = texture(u_tex, v_uv);
  // Iridescent color shift based on position + time
  float angle = v_uv.x * 6.28 + v_uv.y * 3.14 + u_time * 0.5;
  vec3 holo = vec3(
    sin(angle) * 0.5 + 0.5,
    sin(angle + 2.094) * 0.5 + 0.5,
    sin(angle + 4.189) * 0.5 + 0.5
  );
  // Blend holographic over content (subtle overlay)
  fragColor = vec4(mix(color.rgb, holo, 0.15 + 0.1 * sin(u_time)), color.a);
}

注意 2.094 ≈ 2π/3、4.189 ≈ 4π/3,三通道相位均匀错开才产生「白平衡的」彩色循环;混叠系数 0.15 + 0.1*sin(u_time) 让全息强度随脉动呼吸,保持克制才不会抢走内容可读性。

效果 8:扫描线 + CRT(Scan Lines + CRT)

复古显示器观感:扫描线、轻微桶形曲率、荧光粉辉光。适合「代码」「终端」类 beat:

uniform sampler2D u_tex;
uniform float u_time;

void main() {
  vec2 uv = v_uv;
  // Barrel distortion (CRT curvature)
  vec2 centered = uv - 0.5;
  float dist = dot(centered, centered);
  uv = uv + centered * dist * 0.15;

  vec4 color = texture(u_tex, uv);
  // Scan lines
  float scanline = sin(uv.y * 800.0) * 0.04;
  color.rgb -= scanline;
  // Slight RGB offset (phosphor)
  color.r = texture(u_tex, uv + vec2(0.001, 0.0)).r;
  color.b = texture(u_tex, uv - vec2(0.001, 0.0)).b;
  // Vignette
  float vignette = 1.0 - dist * 2.0;
  fragColor = vec4(color.rgb * vignette, 1.0);
}

三段处理各司其职:桶形畸变把边缘向外推(uv + centered * dist * 0.15,dist 是到中心的平方距离);扫描线用高频 sin(uv.y * 800) 做暗纹减光;RGB 通道 ±0.001 的水平偏移模拟荧光粉成像偏移;最后平方距离做暗角。

效果 9:磨砂玻璃模糊(Frosted Glass Blur)

被磨砂玻璃挡住的背后内容——可见但被柔化,带轻微光折射。适合「幕后」「敬请期待」时刻。u_blur 0.0 = 清晰,1.0 = 全磨砂:

uniform sampler2D u_tex;
uniform float u_blur; // 0.0 = clear, 1.0 = full frost

void main() {
  vec2 uv = v_uv;
  vec4 color = vec4(0.0);
  // Box blur with offset
  float radius = u_blur * 0.015;
  for (float x = -2.0; x <= 2.0; x += 1.0) {
    for (float y = -2.0; y <= 2.0; y += 1.0) {
      color += texture(u_tex, uv + vec2(x, y) * radius);
    }
  }
  color /= 25.0;
  // Add frost noise texture
  float frost = fract(sin(dot(uv * 200.0, vec2(12.9898, 78.233))) * 43758.5453);
  color.rgb += frost * 0.03 * u_blur;
  fragColor = color;
}

5×5 循环盒式模糊(25 个采样平均)是单 Pass 里最廉价的近似模糊;之后叠加一层与 u_blur 成正比的颗粒噪声,模拟玻璃内部的霜晶散射。

效果 10:像素排序 / 故障艺术(Pixel Sort / Glitch Art)

像素在竖直或水平条带里自我重排,数字艺术质感。适合科技/创意品牌:

uniform sampler2D u_tex;
uniform float u_intensity; // 0-1

void main() {
  vec2 uv = v_uv;
  // Random horizontal displacement per row
  float row = floor(uv.y * 80.0);
  float noise = fract(sin(row * 127.1) * 43758.5);
  float displace = step(0.7, noise) * u_intensity * 0.1;
  // Shift UV with RGB split
  float r = texture(u_tex, uv + vec2(displace, 0.0)).r;
  float g = texture(u_tex, uv).g;
  float b = texture(u_tex, uv - vec2(displace * 0.5, 0.0)).b;
  fragColor = vec4(r, g, b, 1.0);
}

按行取样(uv.y * 80 划分 80 条扫描带),只有噪声超过 0.7 的「幸运行」才被位移(step(0.7, noise)),从而形成稀疏故障感而非整屏撕裂;u_intensity 从 GSAP 代理驱动,可在时间线里只在一瞬间推高制造抖动。

自建任意自定义效果的通用配方

以上片元着色器本质都是模板。规律永远是四步:

  1. drawElementImage 捕获你的 HTML 内容(复用本文顶部的样板);
  2. 把捕获后的 canvas 上传为 WebGL 纹理
  3. 写一个读取该纹理、输出修改后颜色的片元着色器
  4. 通过 onUpdate 用 GSAP 驱动着色器 uniform

基于此,任何 ShaderToy、The Book of Shaders、CodePen 等渠道的 GLSL 效果都可以迁移到 HyperFrames:

  1. 找一个你中意的效果(搜索 "GLSL [效果名]" 或浏览 shadertoy.com);
  2. 复制其片元着色器;
  3. iResolution 换成 vec2(1920.0, 1080.0),把 iTime 换成你的 u_time uniform;
  4. 追加 uniform sampler2D u_tex; 用于捕获到的内容纹理;
  5. 把各 uniform 接到 GSAP 代理值上。

平面之外,还有更多几何形态

  • SphereGeometry —— 把内容贴到球体上(世界地图、全球触达);
  • CylinderGeometry —— 内容贴到旋转圆柱上(轮播/滚动感);
  • TorusGeometry —— 内容环绕圆环(无限、循环);
  • BoxGeometry —— 内容贴到 3D 盒子上(产品包装、骰子);
  • GLTF 模型 —— 把内容作为屏幕纹理贴到手机、笔记本、显示器上(参见 vfx-iphone-device,即把 GLTF 手机/笔记本与 HTML-in-canvas 屏显组合的 registry block)。

后期链叠加组合(Three.js EffectComposer 多 Pass):

  • Bloom + 胶片颗粒 = 电影感;
  • Bloom + 色差 = 镜头感;
  • 景深 + 暗角 = 聚焦注意力;
  • 胶片颗粒 + 扫描线 = 复古风;
  • Pass 可以无限叠加——想要多少就加多少。

「你并不被此处的效果列表限制。」HTML-in-Canvas API 提供的是原料(任意 HTML 渲染成的纹理),WebGL/Three.js 提供的是对这份原料的无限创作自由。

选型表:HTML-in-Canvas 还是标准 GSAP?

场景 选型 理由
Hero 产品截图展示 HTML-in-Canvas(3D 旋转 + Bloom) 让平面 UI 拥有电影质感
功能列表 / 数据统计 标准 GSAP 内容导向,不需要 3D
CTA / 品牌揭晓 HTML-in-Canvas(传送门或磁吸) 让瞬间值得记住
社会证明 / Logo 墙 标准 GSAP 有序级联,信任感是平稳的
幕间转场 HTML-in-Canvas(粉碎) 戏剧化的幕断
背景氛围 HTML-in-Canvas(液体表面) 高级环境感
快速功能卡片 标准 GSAP 速度优先,3D 会拖慢节奏

表格背后的取舍逻辑与 hyperframes-animation 技能 的运行时选择哲学一致:GSAP 承担 95% 的运动工作(时间线、变换、缓动、交错都足够),HTML-in-Canvas 是有意的、稀缺的、用于制造对比的重型武器。滥用会同时伤害节奏与性能。

仓库内的对应资源与进一步阅读

  • 本文档源文件:html-in-canvas-patterns.md(skill 路由表中标注为「HTML-as-texture + WebGL/GLSL post-fx」入口)
  • 运行时加载方式汇总:hyperframes 能力清单 中「HTML-in-canvas」与「Animation engines」两节(六个确定性运行时适配器的 seek 契约、Three.js 通过 window.__hfThreeTime + hf-seek 事件驱动)
  • WebGPU 变体与渲染环境前提:typegpu.md(liquid-glass 等 block 的浏览器要求、hf-seek 事件契约)
  • 可安装的 VFX blocks 清单:registry 发现文档 中 "VFX (6)" 与 "Liquid Glass (7)" 两个分类表(vfx-shattervfx-magneticvfx-portalvfx-liquid-backgroundvfx-iphone-device 等,可经 registry 机制安装到你的组合工作区)
  • 相邻通用技法:techniques.md(无 3D 依赖的 Canvas 2D、逐字动力学排版、Lottie、可变字体轴等 13 种技法与「何时用什么」映射表,HTML-in-Canvas 是它们之上的重型补充)
  • OpenMontage 侧接入方式:skills/core/hyperframes.mdrender_runtime 决策矩阵、HyperFrames 项目工作区布局、lint/validate/render 验证协议,以及 --workers 1 等实战避坑记录)
登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.14 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
898
5.82 K
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
921
1.84 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.8 K
1.02 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
531
596
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.02 K
519
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.36 K
1.46 K
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
548
391