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