mirror of
https://github.com/heygen-com/hyperframes.git
synced 2026-09-02 12:08:50 +00:00
This reverts commit 3b53bfd2f7.
This commit is contained in:
@@ -1,499 +0,0 @@
|
||||
---
|
||||
title: "Cosmic Orb"
|
||||
description: "An iridescent soap-bubble planet: a slowly spinning sphere of nebula bands, dust lanes and twinkling stars wrapped in a refracting glass limb with chromatic aberration at the edge."
|
||||
---
|
||||
|
||||
import { InstallCommand } from "/snippets/install-command.jsx";
|
||||
import { VariablesExplorer } from "/snippets/variables-explorer.jsx";
|
||||
|
||||
<VariablesExplorer
|
||||
previewSrc="/public/catalog/preview/blocks/cosmic-orb.html"
|
||||
compositionId="cosmic-orb"
|
||||
compositionSrc="compositions/cosmic-orb.html"
|
||||
variables={[{"id":"hue","type":"number","label":"Nebula hue","default":268,"min":0,"max":360,"step":1,"unit":"deg"},{"id":"accent","type":"number","label":"Accent hue","default":196,"min":0,"max":360,"step":1,"unit":"deg"},{"id":"spin","type":"number","label":"Spin rate","default":0.035,"min":0,"max":0.5,"step":0.005,"unit":"turns/s"},{"id":"stars","type":"number","label":"Star density","default":1,"min":0,"max":2,"step":0.05},{"id":"glow","type":"number","label":"Glow intensity","default":1,"min":0,"max":2,"step":0.05},{"id":"size","type":"number","label":"Orb size","default":0.86,"min":0.2,"max":1.2,"step":0.01},{"id":"pulse","type":"number","label":"Beat pulse","default":0,"min":0,"max":1,"step":0.01},{"id":"pulseEnvelope","type":"string","label":"Beat pulse envelope (comma-separated 0-1 samples)","default":"","placeholder":"0,0.2,1,0.4,0"},{"id":"backdrop","type":"color","label":"Backdrop","default":"#04040a"}]}
|
||||
>
|
||||
|
||||
```html cosmic-orb.html
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=1920, height=1080" />
|
||||
<title>Cosmic Orb</title>
|
||||
<script src="https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js"></script>
|
||||
<style>
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
body {
|
||||
background: #000;
|
||||
overflow: hidden;
|
||||
}
|
||||
#co-root {
|
||||
position: relative;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
overflow: hidden;
|
||||
}
|
||||
#co-backdrop {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: #04040a;
|
||||
}
|
||||
#co-canvas {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 1920px;
|
||||
height: 1080px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div
|
||||
id="co-root"
|
||||
data-composition-id="cosmic-orb"
|
||||
data-root="true"
|
||||
data-width="1920"
|
||||
data-height="1080"
|
||||
data-start="0"
|
||||
data-duration="10"
|
||||
data-composition-variables='[
|
||||
{"id":"hue","type":"number","label":"Nebula hue","default":268,"min":0,"max":360,"step":1,"unit":"deg"},
|
||||
{"id":"accent","type":"number","label":"Accent hue","default":196,"min":0,"max":360,"step":1,"unit":"deg"},
|
||||
{"id":"spin","type":"number","label":"Spin rate","default":0.035,"min":0,"max":0.5,"step":0.005,"unit":"turns/s"},
|
||||
{"id":"stars","type":"number","label":"Star density","default":1,"min":0,"max":2,"step":0.05},
|
||||
{"id":"glow","type":"number","label":"Glow intensity","default":1,"min":0,"max":2,"step":0.05},
|
||||
{"id":"size","type":"number","label":"Orb size","default":0.86,"min":0.2,"max":1.2,"step":0.01},
|
||||
{"id":"pulse","type":"number","label":"Beat pulse","default":0,"min":0,"max":1,"step":0.01},
|
||||
{"id":"pulseEnvelope","type":"string","label":"Beat pulse envelope (comma-separated 0-1 samples)","default":"","placeholder":"0,0.2,1,0.4,0"},
|
||||
{"id":"backdrop","type":"color","label":"Backdrop","default":"#04040a"}
|
||||
]'
|
||||
>
|
||||
<div id="co-backdrop"></div>
|
||||
<canvas id="co-canvas" width="1920" height="1080"></canvas>
|
||||
|
||||
<!-- Driver clip: gives HyperFrames a timed element to own on track 0. -->
|
||||
<div
|
||||
id="co-drv"
|
||||
class="clip"
|
||||
data-start="0"
|
||||
data-duration="10"
|
||||
data-track-index="0"
|
||||
style="position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none"
|
||||
></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var DUR = 10;
|
||||
var W = 1920;
|
||||
var H = 1080;
|
||||
|
||||
var ROOT = document.getElementById("co-root");
|
||||
var CS = getComputedStyle(ROOT);
|
||||
|
||||
// `data-composition-variables` is the single owner of every declared
|
||||
// default — parse it rather than repeating each default a second time
|
||||
// in JS. `window.__hyperframes` is NOT guaranteed to exist yet when this
|
||||
// inline script runs, so it can only ever be an override, never the
|
||||
// source. Precedence: host CSS custom property, runtime variable bag,
|
||||
// declared default.
|
||||
var DECL = {};
|
||||
JSON.parse(ROOT.getAttribute("data-composition-variables") || "[]").forEach(function (v) {
|
||||
DECL[v.id] = v.default;
|
||||
});
|
||||
var HF = window.__hyperframes;
|
||||
var V = (HF && HF.getVariables && HF.getVariables()) || {};
|
||||
|
||||
function raw(id) {
|
||||
var css = CS.getPropertyValue("--" + id.toLowerCase()).trim();
|
||||
if (css !== "") return css;
|
||||
if (V[id] !== undefined && V[id] !== "") return V[id];
|
||||
return DECL[id];
|
||||
}
|
||||
function num(id) {
|
||||
var n = parseFloat(raw(id));
|
||||
return isFinite(n) ? n : 0;
|
||||
}
|
||||
function str(id) {
|
||||
var s = raw(id);
|
||||
return typeof s === "string" ? s.trim() : "";
|
||||
}
|
||||
|
||||
var HUE = num("hue");
|
||||
var ACCENT = num("accent");
|
||||
var SPIN = num("spin");
|
||||
var STARS = num("stars");
|
||||
var GLOW = num("glow");
|
||||
var SIZE = num("size");
|
||||
var PULSE = num("pulse");
|
||||
var BACKDROP = str("backdrop");
|
||||
|
||||
document.getElementById("co-backdrop").style.background = BACKDROP;
|
||||
|
||||
// Beat hook. A precomputed envelope (comma-separated 0-1 samples spread
|
||||
// evenly across the clip) is sampled closed-form at time t — no audio
|
||||
// analysis, no accumulator. Empty envelope => the flat `pulse` value.
|
||||
var ENV = str("pulseEnvelope")
|
||||
.split(",")
|
||||
.map(function (s) {
|
||||
return parseFloat(s);
|
||||
})
|
||||
.filter(function (n) {
|
||||
return isFinite(n);
|
||||
});
|
||||
|
||||
function pulseAt(t) {
|
||||
if (ENV.length === 0) return PULSE;
|
||||
if (ENV.length === 1) return ENV[0];
|
||||
var x = Math.min(1, Math.max(0, t / DUR)) * (ENV.length - 1);
|
||||
var i = Math.floor(x);
|
||||
var j = Math.min(i + 1, ENV.length - 1);
|
||||
return ENV[i] + (ENV[j] - ENV[i]) * (x - i);
|
||||
}
|
||||
|
||||
var canvas = document.getElementById("co-canvas");
|
||||
var gl =
|
||||
canvas.getContext("webgl", {
|
||||
alpha: true,
|
||||
antialias: false,
|
||||
depth: false,
|
||||
stencil: false,
|
||||
preserveDrawingBuffer: true,
|
||||
powerPreference: "high-performance",
|
||||
}) ||
|
||||
canvas.getContext("experimental-webgl", {
|
||||
alpha: true,
|
||||
preserveDrawingBuffer: true,
|
||||
});
|
||||
|
||||
var VERT = [
|
||||
"attribute vec2 aPos;",
|
||||
"void main() { gl_Position = vec4(aPos, 0.0, 1.0); }",
|
||||
].join("\n");
|
||||
|
||||
var FRAG = [
|
||||
"precision highp float;",
|
||||
"uniform vec2 uRes;",
|
||||
"uniform float uTime;",
|
||||
"uniform float uRadius;",
|
||||
"uniform float uSpin;",
|
||||
"uniform float uHue;",
|
||||
"uniform float uAccent;",
|
||||
"uniform float uStars;",
|
||||
"uniform float uGlow;",
|
||||
"uniform float uPulse;",
|
||||
"const float TAU = 6.28318531;",
|
||||
"",
|
||||
"// One cheap hash for every random-looking thing in here.",
|
||||
"float h1(float x) { return fract(sin(x * 127.1) * 43758.5453); }",
|
||||
"float h2(vec2 p) { return h1(dot(p, vec2(1.0, 157.31))); }",
|
||||
"",
|
||||
"vec3 hue2rgb(float h) {",
|
||||
" return clamp(abs(mod(h * 6.0 + vec3(0.0, 4.0, 2.0), 6.0) - 3.0) - 1.0, 0.0, 1.0);",
|
||||
"}",
|
||||
"",
|
||||
"vec3 rotX(vec3 p, float a) { float c = cos(a), s = sin(a); return vec3(p.x, c * p.y - s * p.z, s * p.y + c * p.z); }",
|
||||
"vec3 rotY(vec3 p, float a) { float c = cos(a), s = sin(a); return vec3(c * p.x + s * p.z, p.y, -s * p.x + c * p.z); }",
|
||||
"vec3 rotZ(vec3 p, float a) { float c = cos(a), s = sin(a); return vec3(c * p.x - s * p.y, s * p.x + c * p.y, p.z); }",
|
||||
"",
|
||||
"vec3 safeDir(vec3 v) {",
|
||||
" float l = dot(v, v);",
|
||||
" if (l < 1e-6) return vec3(0.0, 0.0, -1.0);",
|
||||
" return v * inversesqrt(l);",
|
||||
"}",
|
||||
"",
|
||||
"// Fixed axial tilt, then spin about the tilted polar axis.",
|
||||
"vec3 toBody(vec3 n, float spin) { return rotY(rotZ(rotX(n, -0.34), 0.42), -spin); }",
|
||||
"vec2 lonlat(vec3 d) { return vec2(atan(d.x, d.z), asin(clamp(d.y, -1.0, 1.0))); }",
|
||||
"",
|
||||
"float dens(float base) { return clamp(1.0 - (1.0 - base) * uStars, 0.0, 1.0); }",
|
||||
"",
|
||||
"// One star size-class: cell grid, seeded jitter, soft round core.",
|
||||
"float starField(vec2 q, float freq, float base, float rad) {",
|
||||
" vec2 g = q * freq;",
|
||||
" vec2 id = floor(g);",
|
||||
" float h = h2(id);",
|
||||
" if (h < dens(base)) return 0.0;",
|
||||
" vec2 c = vec2(h2(id + vec2(3.7, 1.3)), h2(id + vec2(9.1, 5.5)));",
|
||||
" float d = length(fract(g) - c);",
|
||||
" float core = smoothstep(rad, 0.0, d);",
|
||||
" // Twinkle: a per-star phase driven straight off uTime, no accumulator.",
|
||||
" float tw = 0.62 + 0.38 * sin(uTime * 2.4 + h * 53.7);",
|
||||
" return core * core * (0.45 + 0.55 * h1(h * 91.7)) * tw;",
|
||||
"}",
|
||||
"",
|
||||
"// 4-point diffraction glare, only worth paying for on the brightest class.",
|
||||
"float starGlare(vec2 q, float freq, float base) {",
|
||||
" vec2 g = q * freq;",
|
||||
" vec2 id = floor(g);",
|
||||
" float h = h2(id);",
|
||||
" if (h < dens(base)) return 0.0;",
|
||||
" vec2 c = vec2(h2(id + vec2(3.7, 1.3)), h2(id + vec2(9.1, 5.5)));",
|
||||
" vec2 dv = abs(fract(g) - c);",
|
||||
" float hx = exp(-dv.x * 70.0) * exp(-dv.y * 9.0);",
|
||||
" float hy = exp(-dv.y * 70.0) * exp(-dv.x * 9.0);",
|
||||
" return max(hx, hy) * 0.45;",
|
||||
"}",
|
||||
"",
|
||||
"// Three size-classes at ~6 / 11 / 19 cell frequency.",
|
||||
"float starsAll(vec2 q, float gain) {",
|
||||
" float s = starField(q, 6.0, 0.958, 0.20);",
|
||||
" s += starGlare(q, 6.0, 0.958);",
|
||||
" s += starField(q, 11.0, 0.920, 0.18) * 0.95;",
|
||||
" s += starField(q, 19.0, 0.865, 0.17) * 0.75;",
|
||||
" return s * gain;",
|
||||
"}",
|
||||
"",
|
||||
"vec3 nebula(vec2 q) {",
|
||||
" // Two sin-field turbulence layers.",
|
||||
" float t1 = sin(q.x * 3.1 + sin(q.y * 2.7) * 1.9) * sin(q.y * 4.3 + sin(q.x * 1.7) * 2.3);",
|
||||
" float t2 = sin(q.x * 7.9 + sin(q.y * 5.1) * 1.3) * sin(q.y * 9.7 + sin(q.x * 4.4) * 1.1);",
|
||||
" float turb = t1 * 0.66 + t2 * 0.34;",
|
||||
"",
|
||||
" // Galaxy bands, warped by the turbulence.",
|
||||
" float band = sin(q.y * 3.2 + turb * 1.7 + q.x * 0.55);",
|
||||
" float bands = pow(max(0.0, band * 0.5 + 0.5), 3.2);",
|
||||
"",
|
||||
" // Dust lanes: broad darkened swathes, not a thin curve.",
|
||||
" float lane = sin(q.y * 2.9 + q.x * 1.3 + t1 * 1.6);",
|
||||
" float dust = 0.22 + 0.78 * smoothstep(-0.45, 0.75, lane);",
|
||||
"",
|
||||
" // Core bulge.",
|
||||
" float dc = length(vec2((q.x - 0.55) * 0.5, (q.y + 0.12) * 1.1));",
|
||||
" float core = exp(-dc * dc * 2.6);",
|
||||
"",
|
||||
" // Two pocket glows.",
|
||||
" float dA = length(vec2((q.x + 1.95) * 0.62, (q.y - 0.52) * 1.45));",
|
||||
" float dB = length(vec2((q.x - 2.35) * 0.55, (q.y + 0.78) * 1.30));",
|
||||
" float pA = exp(-dA * dA * 4.0);",
|
||||
" float pB = exp(-dB * dB * 5.0);",
|
||||
"",
|
||||
" vec3 cNeb = hue2rgb(uHue / 360.0);",
|
||||
" vec3 cAcc = hue2rgb(uAccent / 360.0);",
|
||||
" vec3 cWarm = hue2rgb(uHue / 360.0 + 0.07);",
|
||||
"",
|
||||
" vec3 col = mix(cNeb, cWarm, 0.5 + 0.5 * turb) * bands * dust * 0.17;",
|
||||
" col += mix(cNeb, vec3(1.0), 0.50) * core * dust * 0.13;",
|
||||
" col += mix(cAcc, vec3(1.0), 0.60) * pA * 0.30 * uGlow;",
|
||||
" col += mix(cNeb, vec3(1.0), 0.50) * pB * 0.24 * uGlow;",
|
||||
" return col;",
|
||||
"}",
|
||||
"",
|
||||
"void main() {",
|
||||
" vec2 p = (gl_FragCoord.xy - uRes * 0.5) / uRadius;",
|
||||
" float r = length(p);",
|
||||
" float aa = 1.4 / uRadius;",
|
||||
" float spin = TAU * uSpin * uTime;",
|
||||
"",
|
||||
" vec3 cNeb = hue2rgb(uHue / 360.0);",
|
||||
" vec3 cAcc = hue2rgb(uAccent / 360.0);",
|
||||
"",
|
||||
" float mask = smoothstep(1.0 + aa, 1.0 - aa, r);",
|
||||
" float halo = exp(-max(0.0, r - 1.0) * 13.0) * (1.0 - mask);",
|
||||
"",
|
||||
" vec3 body = vec3(0.0);",
|
||||
" if (mask > 0.001) {",
|
||||
" float rc = min(r, 1.0);",
|
||||
" // Analytic sphere: the normal falls straight out of z = sqrt(1 - r^2).",
|
||||
" float z = sqrt(max(0.0, 1.0 - rc * rc));",
|
||||
" vec3 N = vec3(p.x, p.y, z);",
|
||||
" vec2 q = lonlat(toBody(safeDir(N), spin));",
|
||||
"",
|
||||
" float gain = 0.9 + 2.6 * uPulse;",
|
||||
" body = nebula(q);",
|
||||
" body += vec3(1.0) * starsAll(q, gain) * (0.95 + 0.15 * uGlow);",
|
||||
"",
|
||||
" // Limb darkening.",
|
||||
" body *= mix(0.32, 1.0, pow(z, 0.5));",
|
||||
"",
|
||||
" // Refract-sampled back layer, split per channel: the chromatic",
|
||||
" // aberration that reads as glass at the limb.",
|
||||
" vec3 I = vec3(0.0, 0.0, -1.0);",
|
||||
" vec3 dR = safeDir(refract(I, N, 1.0 / 1.09));",
|
||||
" vec3 dG = safeDir(refract(I, N, 1.0 / 1.13));",
|
||||
" vec3 dB = safeDir(refract(I, N, 1.0 / 1.17));",
|
||||
" vec2 qR = lonlat(toBody(dR, spin));",
|
||||
" vec2 qG = lonlat(toBody(dG, spin));",
|
||||
" vec2 qB = lonlat(toBody(dB, spin));",
|
||||
" vec3 back = vec3(starsAll(qR, gain), starsAll(qG, gain), starsAll(qB, gain));",
|
||||
" float fres = pow(1.0 - z, 1.8);",
|
||||
" body += back * fres * 2.2;",
|
||||
" body += nebula(qG) * fres * 0.8;",
|
||||
"",
|
||||
" // Aurora sheen riding the glass shell.",
|
||||
" float ang = atan(p.y, p.x);",
|
||||
" float sheen = smoothstep(0.72, 0.99, r) * smoothstep(1.0, 0.90, r);",
|
||||
" float w = 0.5 + 0.5 * sin(ang * 2.0 + spin * 1.6);",
|
||||
" body += (mix(cNeb, cAcc, w) * 0.55 + vec3(0.16)) * sheen * 0.30 * uGlow;",
|
||||
"",
|
||||
" // Three speculars, fixed in screen space: the key light does not spin.",
|
||||
" vec2 a1 = p - vec2(-0.34, 0.62);",
|
||||
" vec2 a2 = p - vec2(0.58, 0.60);",
|
||||
" vec2 a3 = p - vec2(0.24, -0.80);",
|
||||
" float sp = exp(-dot(a1, a1) * 30.0) * 0.30;",
|
||||
" sp += exp(-dot(a2, a2) * 150.0) * 0.80;",
|
||||
" sp += exp(-dot(a3, a3) * 70.0) * 0.30;",
|
||||
" body += vec3(1.0) * sp * (0.30 + 0.70 * pow(1.0 - z, 1.5)) * uGlow;",
|
||||
"",
|
||||
" // Fresnel void glow hugging the inside of the rim.",
|
||||
" body += mix(cAcc, vec3(1.0), 0.4) * pow(1.0 - z, 6.0) * 0.30 * uGlow;",
|
||||
" }",
|
||||
"",
|
||||
" vec3 haloCol = mix(cNeb, cAcc, 0.35);",
|
||||
" vec3 outCol = body * mask + haloCol * halo * 0.22 * uGlow;",
|
||||
" float outA = clamp(mask + halo * 0.16 * uGlow, 0.0, 1.0);",
|
||||
" gl_FragColor = vec4(clamp(outCol, 0.0, 4.0), outA);",
|
||||
"}",
|
||||
].join("\n");
|
||||
|
||||
var uni = {};
|
||||
var ready = false;
|
||||
|
||||
function compile(type, src) {
|
||||
var sh = gl.createShader(type);
|
||||
gl.shaderSource(sh, src);
|
||||
gl.compileShader(sh);
|
||||
if (!gl.getShaderParameter(sh, gl.COMPILE_STATUS)) {
|
||||
throw new Error("cosmic-orb shader: " + gl.getShaderInfoLog(sh));
|
||||
}
|
||||
return sh;
|
||||
}
|
||||
|
||||
if (gl) {
|
||||
var prog = gl.createProgram();
|
||||
gl.attachShader(prog, compile(gl.VERTEX_SHADER, VERT));
|
||||
gl.attachShader(prog, compile(gl.FRAGMENT_SHADER, FRAG));
|
||||
gl.linkProgram(prog);
|
||||
if (!gl.getProgramParameter(prog, gl.LINK_STATUS)) {
|
||||
throw new Error("cosmic-orb link: " + gl.getProgramInfoLog(prog));
|
||||
}
|
||||
gl.useProgram(prog);
|
||||
|
||||
var buf = gl.createBuffer();
|
||||
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
||||
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 3, -1, -1, 3]), gl.STATIC_DRAW);
|
||||
var loc = gl.getAttribLocation(prog, "aPos");
|
||||
gl.enableVertexAttribArray(loc);
|
||||
gl.vertexAttribPointer(loc, 2, gl.FLOAT, false, 0, 0);
|
||||
|
||||
[
|
||||
"uRes",
|
||||
"uTime",
|
||||
"uRadius",
|
||||
"uSpin",
|
||||
"uHue",
|
||||
"uAccent",
|
||||
"uStars",
|
||||
"uGlow",
|
||||
"uPulse",
|
||||
].forEach(function (n) {
|
||||
uni[n] = gl.getUniformLocation(prog, n);
|
||||
});
|
||||
|
||||
gl.viewport(0, 0, W, H);
|
||||
gl.uniform2f(uni.uRes, W, H);
|
||||
gl.uniform1f(uni.uRadius, (SIZE * H) / 2);
|
||||
gl.uniform1f(uni.uSpin, SPIN);
|
||||
gl.uniform1f(uni.uHue, HUE);
|
||||
gl.uniform1f(uni.uAccent, ACCENT);
|
||||
gl.uniform1f(uni.uStars, STARS);
|
||||
gl.uniform1f(uni.uGlow, GLOW);
|
||||
ready = true;
|
||||
}
|
||||
|
||||
// Every frame is computed from t alone: spin is spin_rate * t, the
|
||||
// pulse is sampled from the envelope at t. No accumulators, no clocks.
|
||||
function draw(t) {
|
||||
if (!ready) return;
|
||||
gl.uniform1f(uni.uTime, t);
|
||||
gl.uniform1f(uni.uPulse, pulseAt(t));
|
||||
gl.clearColor(0, 0, 0, 0);
|
||||
gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
||||
gl.flush();
|
||||
}
|
||||
|
||||
window.__timelines = window.__timelines || {};
|
||||
var tl = gsap.timeline({ paused: true });
|
||||
|
||||
// The canvas is repainted from a property SETTER, not from onUpdate:
|
||||
// gsap's seek(t) suppresses events by default, so an onUpdate callback
|
||||
// silently never fires on a scrub and the canvas freezes on frame 0.
|
||||
// Tweened values are always written during render, suppressed or not,
|
||||
// so this fires on every seek — and hands us the frame time directly.
|
||||
var driver = { _t: 0 };
|
||||
Object.defineProperty(driver, "t", {
|
||||
get: function () {
|
||||
return this._t;
|
||||
},
|
||||
set: function (v) {
|
||||
this._t = v;
|
||||
draw(v);
|
||||
},
|
||||
});
|
||||
tl.to(driver, { t: DUR, duration: DUR, ease: "none" }, 0);
|
||||
window.__timelines["cosmic-orb"] = tl;
|
||||
|
||||
draw(0);
|
||||
})();
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
</VariablesExplorer>
|
||||
|
||||
## Install
|
||||
|
||||
<InstallCommand command="npx hyperframes add cosmic-orb" />
|
||||
|
||||
That writes one file: `compositions/cosmic-orb.html`.
|
||||
|
||||
## Add it to your video
|
||||
|
||||
It runs for 10 seconds at 1920×1080. Paste this into your composition:
|
||||
|
||||
```html index.html
|
||||
<div
|
||||
data-composition-id="cosmic-orb"
|
||||
data-composition-src="compositions/cosmic-orb.html"
|
||||
data-start="0"
|
||||
data-duration="10"
|
||||
data-track-index="1"
|
||||
data-width="1920"
|
||||
data-height="1080"
|
||||
></div>
|
||||
```
|
||||
|
||||
Move it in time with `data-start`. Put it on a different timeline row with
|
||||
`data-track-index`. See [data attributes](/concepts/data-attributes) for the rest.
|
||||
|
||||
## Change how it looks
|
||||
|
||||
Set these CSS variables on the block:
|
||||
|
||||
- `--hue` — Nebula hue. Defaults to `268`.
|
||||
- `--accent` — Accent hue. Defaults to `196`.
|
||||
- `--spin` — Spin rate (turns per second). Defaults to `0.035`.
|
||||
- `--stars` — Star density. Defaults to `1`.
|
||||
- `--glow` — Glow intensity. Defaults to `1`.
|
||||
- `--size` — Orb size (fraction of frame height). Defaults to `0.86`.
|
||||
- `--pulse` — Beat pulse (0-1, flat value when no envelope is set). Defaults to `0`.
|
||||
- `--pulseenvelope` — Beat pulse envelope: comma-separated 0-1 samples spread evenly across the clip. Defaults to ``.
|
||||
- `--backdrop` — Backdrop. Defaults to `#04040a`.
|
||||
|
||||
{/* hf:generated-footer */}
|
||||
|
||||
Tagged `webgl` `shader` `background` `showcase` `3d`.
|
||||
|
||||
## Related topics
|
||||
|
||||
- [Browse the complete Catalog](/catalog)
|
||||
- [Add assets and Catalog items in Studio](/studio/assets-and-blocks)
|
||||
- [Build a richer composition](/go-further)
|
||||
Reference in New Issue
Block a user