Setting the file. One moment.
Glass Shard Title · Glass Shard Title · heygen-com/hyperframes · Skills Docs
ContentsBack to the top of the page (opens in a new tab)
glass-shard-title.html
HTML · 348 lines · 16 KB
1 <! doctype html >
2 < html
3 lang = "en"
4 data-composition-variables = '[{"id":"headline","type":"string","label":"Headline","default":"Designed in glass","maxLength":40},{"id":"tileCount","type":"number","label":"Tiles","default":8,"min":1,"max":400,"step":1},{"id":"roundness","type":"number","label":"Roundness (0-1)","default":0.4,"min":0,"max":1,"step":0.01},{"id":"bevel","type":"number","label":"Bevel (0-1)","default":0.35,"min":0,"max":1,"step":0.01},{"id":"meshSmooth","type":"number","label":"Surface smoothness (0-1)","default":0.6,"min":0,"max":1,"step":0.01},{"id":"flyInTime","type":"number","label":"Fly-in time (s)","default":2.3,"min":0.2,"max":6,"step":0.05},{"id":"flyOutTime","type":"number","label":"Fly-out time (s)","default":2.4,"min":0.2,"max":6,"step":0.05},{"id":"stagger","type":"number","label":"Stagger (0-1)","default":0.27,"min":0,"max":1,"step":0.01},{"id":"flyInRotation","type":"number","label":"Fly-in rotation (0-60)","description":"Amount of inbound tumbling over the entire flight. 0 disables flight rotation; final orientation lands with each shard position.","default":5,"min":0,"max":60,"step":0.1},{"id":"flyOutRotation","type":"number","label":"Fly-out rotation (0-6)","default":6,"min":0,"max":6,"step":0.1},{"id":"chaos","type":"number","label":"Outline chaos (0-1)","default":0.25,"min":0,"max":1,"step":0.01},{"id":"padding","type":"number","label":"Edge padding (0-1)","default":1,"min":0,"max":1,"step":0.01},{"id":"sizeVariance","type":"number","label":"Size variance (0-1)","default":0.35,"min":0,"max":1,"step":0.01},{"id":"gap","type":"number","label":"Tile gap","default":0.03,"min":0,"max":0.3,"step":0.002},{"id":"easePow","type":"number","label":"Fly-in position ease (1-10)","description":"Shapes lateral and depth travel. Rotation uses the same staggered flight window with a gentle settle through arrival.","default":10,"min":1,"max":10,"step":0.1},{"id":"sideDist","type":"number","label":"Side fly distance","default":3,"min":0,"max":60,"step":0.5},{"id":"zDist","type":"number","label":"Z fly-from (negative)","default":-42,"min":-400,"max":0,"step":2},{"id":"zOut","type":"number","label":"Z fly-out to (+ = past camera)","default":14,"min":-400,"max":60,"step":2},{"id":"fog","type":"number","label":"Fog distance (0 = off)","default":36,"min":0,"max":400,"step":2}]'
5 >
6 < head >
7 < script >
8 /* ?play standalone mode only: this file lives in compositions/ but its
9 asset paths are project-root-relative (they resolve there when the
10 runtime inlines it into the host). Never runs for Studio/render. */
11 if ( new URLSearchParams (location.search). has ( "play" )) document. write ( '<base href="../">' );
12 </ script >
13
14 < meta charset = "UTF-8" />
15 < meta name = "viewport" content = "width=1920, height=1080" />
16 < title >Glass Shard Title</ title >
17 < script src = "https://cdn.jsdelivr.net/npm/gsap@3.14.2/dist/gsap.min.js" ></ script >
18 < script src = "https://cdn.jsdelivr.net/npm/d3-delaunay@6.0.4/dist/d3-delaunay.min.js" ></ script >
19 < style >
20 @font-face {
21 font-family : "Geist" ;
22 src : url ( "assets/fonts/Geist-Regular.ttf" ) format ( "truetype" );
23 font-weight : 400 ;
24 font-style : normal ;
25 }
26 @font-face {
27 font-family : "Geist" ;
28 src : url ( "assets/fonts/Geist-SemiBold.ttf" ) format ( "truetype" );
29 font-weight : 600 ;
30 font-style : normal ;
31 }
32 @font-face {
33 font-family : "Geist" ;
34 src : url ( "assets/fonts/Geist-Bold.ttf" ) format ( "truetype" );
35 font-weight : 700 ;
36 font-style : normal ;
37 }
38 * {
39 margin : 0 ;
40 padding : 0 ;
41 box-sizing : border-box ;
42 }
43 html ,
44 body {
45 width : 1920 px ;
46 height : 1080 px ;
47 overflow : hidden ;
48 background : #0a0a0f ;
49 }
50 body {
51 font-family : "Geist" , ui-sans-serif , system-ui , sans-serif ;
52 }
53 #gst-root {
54 position : relative ;
55 width : 1920 px ;
56 height : 1080 px ;
57 overflow : hidden ;
58 background : #0a0a0f ; /* flat — no gradients, no glow */
59 }
60 .clip {
61 position : absolute ;
62 inset : 0 ;
63 }
64 #gst-canvas {
65 display : block ;
66 width : 100 % ;
67 height : 100 % ;
68 }
69 #gst-fontload {
70 position : absolute ;
71 opacity : 0 ;
72 pointer-events : none ;
73 }
74 </ style >
75 </ head >
76 < body >
77 < div
78 data-hf-id = "hf-51pv"
79 id = "gst-root"
80 data-composition-id = "glass-shard-title"
81 data-start = "0"
82 data-duration = "12.16"
83 data-width = "1920"
84 data-height = "1080"
85 >
86 < div
87 data-hf-id = "hf-lsju"
88 id = "gst-canvas-clip"
89 class = "clip"
90 data-start = "0"
91 data-duration = "12.16"
92 data-track-index = "1"
93 data-media-start = "0"
94 ></ div >
95 < div
96 data-hf-id = "hf-uo1i"
97 id = "gst-fontload"
98 aria-hidden = "true"
99 data-start = "0"
100 data-duration = "12.16"
101 data-media-start = "0"
102 >
103 < span data-hf-id = "hf-kqtg" style = "font-weight: 400" >Aa</ span
104 >< span data-hf-id = "hf-7bxm" style = "font-weight: 600" >Aa</ span >
105 </ div >
106 </ div >
107
108 < script >
109 /* ================================================================
110 glass-shard-title — iridescent glass shards fly in from the left
111 and right edges, assemble into the headline, idle with a slight
112 rotation, then fly back out and leave the frame empty.
113
114 The ONLY content is the headline. Flat dark background.
115
116 Seek-safety: the timeline drives two master progresses (tin, tout)
117 plus the material resolve; every per-shard position/rotation is a
118 pure function of those masters and st.time. No rAF, no
119 integrators, no Math.random(). Shard layout is seeded and built
120 after fonts load (cell selection samples the rasterised text).
121 ================================================================ */
122 window.__timelines = window.__timelines || {};
123 /* Studio's variables/SDK parser fails on any composition with a <canvas>
124 in its MARKUP (verified by bisection) — so the canvas is created at
125 runtime instead. Identical for preview/render; invisible to the parser.
126
127 Guarded: if this script is evaluated twice in one document a second
128 <canvas id="gst-canvas"> would be appended, getElementById would keep
129 returning the FIRST one, and the second three.js renderer would be
130 built on a canvas that already owns a live WebGL context. */
131 ( function () {
132 if (document. getElementById ( "gst-canvas" )) return ;
133 var c = document. createElement ( "canvas" );
134 c.id = "gst-canvas" ;
135 c.width = 1920 ;
136 c.height = 1080 ;
137 document. getElementById ( "gst-canvas-clip" ). appendChild (c);
138 })();
139
140 window.gstMulberry32 = gstMulberry32;
141 function gstMulberry32 ( seed ) {
142 return function () {
143 var s = (seed = (seed + 0x6d2b79f5 ) | 0 );
144 var t = Math. imul (s ^ (s >>> 15 ), 1 | s);
145 t = (t + Math. imul (t ^ (t >>> 7 ), 61 | t)) ^ t;
146 return ((t ^ (t >>> 14 )) >>> 0 ) / 4294967296 ;
147 };
148 }
149
150 ( function () {
151 var DUR = 9 ;
152
153 /* ---- Studio variables ---- */
154 var vars = {
155 headline: "Designed in glass" ,
156 tileCount: 8 ,
157 roundness: 0.4 ,
158 bevel: 0.35 ,
159 meshSmooth: 0.6 ,
160 flyInTime: 2.3 ,
161 flyOutTime: 2.4 ,
162 stagger: 0.27 ,
163 flyInRotation: 5 ,
164 flyOutRotation: 6 ,
165 chaos: 0.25 ,
166 padding: 1 ,
167 sizeVariance: 0.35 ,
168 gap: 0.03 ,
169 easePow: 10 ,
170 sideDist: 3 ,
171 zDist: - 42 ,
172 zOut: 14 ,
173 fog: 36 ,
174 };
175 try {
176 if (window.__hyperframes && window.__hyperframes.getVariables) {
177 var v = window.__hyperframes. getVariables () || {};
178 if (v.headline) vars.headline = String (v.headline);
179 if (v.title) vars.headline = String (v.title); /* legacy id */
180 if (v.tileCount !== undefined && isFinite ( Number (v.tileCount)))
181 vars.tileCount = Number (v.tileCount);
182 if (v.roundness !== undefined && isFinite ( Number (v.roundness)))
183 vars.roundness = Number (v.roundness);
184 if (v.bevel !== undefined && isFinite ( Number (v.bevel))) vars.bevel = Number (v.bevel);
185 if (v.meshSmooth !== undefined && isFinite ( Number (v.meshSmooth)))
186 vars.meshSmooth = Number (v.meshSmooth);
187 if (v.flyInTime !== undefined && isFinite ( Number (v.flyInTime)))
188 vars.flyInTime = Number (v.flyInTime);
189 if (v.flyOutTime !== undefined && isFinite ( Number (v.flyOutTime)))
190 vars.flyOutTime = Number (v.flyOutTime);
191 if (v.stagger !== undefined && isFinite ( Number (v.stagger)))
192 vars.stagger = Number (v.stagger);
193 /* Legacy callers may still provide spin. New controls override it
194 independently; the old multiplier/default keeps its meaning. */
195 if (v.spin !== undefined && isFinite ( Number (v.spin))) {
196 vars.flyInRotation = vars.flyOutRotation = Math. max ( 0 , Math. min ( 6 , Number (v.spin)));
197 }
198 if (v.flyInRotation !== undefined && isFinite ( Number (v.flyInRotation)))
199 vars.flyInRotation = Number (v.flyInRotation);
200 if (v.flyOutRotation !== undefined && isFinite ( Number (v.flyOutRotation)))
201 vars.flyOutRotation = Number (v.flyOutRotation);
202 if (v.zOut !== undefined && isFinite ( Number (v.zOut))) vars.zOut = Number (v.zOut);
203 if (v.chaos !== undefined && isFinite ( Number (v.chaos))) vars.chaos = Number (v.chaos);
204 if (v.padding !== undefined && isFinite ( Number (v.padding)))
205 vars.padding = Number (v.padding);
206 if (v.sizeVariance !== undefined && isFinite ( Number (v.sizeVariance)))
207 vars.sizeVariance = Number (v.sizeVariance);
208 if (v.gap !== undefined && isFinite ( Number (v.gap))) vars.gap = Number (v.gap);
209 if (v.easePow !== undefined && isFinite ( Number (v.easePow)))
210 vars.easePow = Number (v.easePow);
211 if (v.sideDist !== undefined && isFinite ( Number (v.sideDist)))
212 vars.sideDist = Number (v.sideDist);
213 if (v.zDist !== undefined && isFinite ( Number (v.zDist))) vars.zDist = Number (v.zDist);
214 if (v.fog !== undefined && isFinite ( Number (v.fog))) vars.fog = Number (v.fog);
215 }
216 } catch (e) {
217 /* keep defaults */
218 }
219 vars.tileCount = Math. max ( 1 , Math. min ( 400 , Math. round (vars.tileCount)));
220 vars.roundness = Math. max ( 0 , Math. min ( 1 , vars.roundness));
221 vars.bevel = Math. max ( 0 , Math. min ( 1 , vars.bevel));
222 vars.meshSmooth = Math. max ( 0 , Math. min ( 1 , vars.meshSmooth));
223 vars.flyInTime = Math. max ( 0.2 , Math. min ( 6 , vars.flyInTime));
224 vars.flyOutTime = Math. max ( 0.2 , Math. min ( 6 , vars.flyOutTime));
225 vars.stagger = Math. max ( 0 , Math. min ( 1 , vars.stagger));
226 vars.flyInRotation = Math. max ( 0 , Math. min ( 60 , vars.flyInRotation));
227 vars.flyOutRotation = Math. max ( 0 , Math. min ( 6 , vars.flyOutRotation));
228 vars.zOut = Math. max ( - 400 , Math. min ( 60 , vars.zOut));
229 vars.chaos = Math. max ( 0 , Math. min ( 1 , vars.chaos));
230 vars.padding = Math. max ( 0 , Math. min ( 1 , vars.padding));
231 vars.sizeVariance = Math. max ( 0 , Math. min ( 1 , vars.sizeVariance));
232 vars.gap = Math. max ( 0 , Math. min ( 0.3 , vars.gap));
233 vars.easePow = Math. max ( 1 , Math. min ( 10 , vars.easePow));
234 vars.sideDist = Math. max ( 0 , Math. min ( 60 , vars.sideDist));
235 /* zDist is a coordinate: accept "-200" style input, clamp behind pane. */
236 vars.zDist = Math. min ( 0 , Math. max ( - 400 , vars.zDist > 0 ? - vars.zDist : vars.zDist));
237 vars.fog = Math. max ( 0 , Math. min ( 400 , vars.fog));
238
239 /* ---- Phase windows (speed compresses fly phases, hold absorbs) ---- */
240 var IN_START = 0.12 ;
241 var OUT_END = DUR - 0.35 ;
242 /* Explicit flight durations; if in + out + a minimum hold exceed the
243 composition, both scale down proportionally. */
244 var MIN_HOLD = 0.5 ;
245 var avail = OUT_END - IN_START - MIN_HOLD ;
246 var tIn = vars.flyInTime,
247 tOut = vars.flyOutTime;
248 if (tIn + tOut > avail) {
249 var k = avail / (tIn + tOut);
250 tIn *= k;
251 tOut *= k;
252 }
253 var IN_WINDOW = tIn;
254 var OUT_WINDOW = tOut;
255 var OUT_START = OUT_END - OUT_WINDOW ;
256
257 /* Scripted state read by renderScene. */
258 var st = {
259 time: 0 ,
260 tin: 0 /* master fly-in progress 0..1 */ ,
261 tout: 0 /* master fly-out progress 0..1 */ ,
262 thickness: 0.5 ,
263 roughness: 0.07 ,
264 ior: 1.52 ,
265 };
266
267 window.__GST = { DUR: DUR , st: st, vars: vars };
268
269 /* ---- Timeline: paused, registered, hf-seek wired ---- */
270 var tl = gsap. timeline ({ paused: true });
271 tl. eventCallback ( "onUpdate" , function () {
272 if (window.__gstRender) window. __gstRender ();
273 });
274 /* Studio's player seeks with GSAP events suppressed and dispatches an
275 hf-seek CustomEvent instead — re-sync and repaint so the stage follows. */
276 /* Exactly one listener and one live timeline per document. A second
277 evaluation of this script would otherwise stack another hf-seek
278 listener and leave the previous paused timeline registered, so every
279 seek would drive N timelines and repaint N times. Declared as a
280 named function (not an arrow) so the reference read back off window
281 is identical and removeEventListener actually matches. */
282 function gstOnSeek ( event ) {
283 var d = event && event.detail;
284 if (d && typeof d.time === "number" )
285 tl. totalTime (Math. min (d.time, tl. totalDuration ()), true );
286 var fn = tl. eventCallback ( "onUpdate" );
287 if (fn) fn ();
288 }
289 if (window.__gstSeekHandler) window. removeEventListener ( "hf-seek" , window.__gstSeekHandler);
290 if (window.__gstTimeline && window.__gstTimeline !== tl) {
291 try {
292 window.__gstTimeline. kill ();
293 } catch (e) {
294 /* best effort */
295 }
296 }
297 window.__gstSeekHandler = gstOnSeek;
298 window.__gstTimeline = tl;
299 window. addEventListener ( "hf-seek" , gstOnSeek);
300 /* Release the listener and the timeline with the document. Skipped for
301 a bfcache'd page, which is coming back with this stage still live. */
302 window. addEventListener ( "pagehide" , function ( event ) {
303 if (event && event.persisted === true ) return ;
304 window. removeEventListener ( "hf-seek" , gstOnSeek);
305 window.__gstSeekHandler = null ;
306 window.__gstTimeline = null ;
307 try {
308 tl. kill ();
309 } catch (e) {
310 /* best effort */
311 }
312 });
313
314 tl. to (st, { time: DUR , duration: DUR , ease: "none" }, 0 );
315 tl. to (st, { tin: 1 , duration: IN_WINDOW , ease: "none" }, IN_START );
316 tl. to (st, { tout: 1 , duration: OUT_WINDOW , ease: "none" }, OUT_START );
317
318 /* Glass stays clear throughout. The old frosted->clear resolve made
319 still-flying shards transmit a BLURRED copy of the already-seated
320 text — the ghost headline — so it is gone. */
321
322 window.__timelines[ "glass-shard-title" ] = tl;
323 })();
324 </ script >
325
326 < script src = "assets/glass-main.js" ></ script >
327 < script >
328 /* Standalone playback: open this file with ?play (add &loop to repeat).
329 Inert without the param — Studio and the renderer never add it, so
330 editing and deterministic renders are unaffected. */
331 ( function () {
332 var q = new URLSearchParams (location.search);
333 if ( ! q. has ( "play" )) return ;
334 var tick = setInterval ( function () {
335 var map = window.__timelines || {};
336 var ids = Object. keys (map);
337 if ( ! ids. length ) return ;
338 clearInterval (tick);
339 for ( var i = 0 ; i < ids. length ; i ++ ) {
340 var tl = map[ids[i]];
341 if (q. has ( "loop" )) tl. repeat ( - 1 );
342 tl. play ( 0 );
343 }
344 }, 100 );
345 })();
346 </ script >
347 </ body >
348 </ html >