Setting the file. One moment. Scene · Music To Video · heygen-com/hyperframes · Skills DocsGsap Min
(opens in a new tab)
references/motion-primitives/gooey-metaball/scene.html
HTML·206 lines·5 KB
7 --hg-cyan: #2afff0;
8 --hg-bg: #0a0a0f;
9 --hg-fg: #f5f5fa;
10 --hg-dim: #6b6b78;
11 }
12 * {
13 margin: 0;
14 padding: 0;
15 box-sizing: border-box;
16 }
17 .hero {
18 position: absolute;
19 inset: 0;
20 display: flex;
21 align-items: center;
22 justify-content: center;
23 font-weight: 900;
24 font-size: 280px;
25 letter-spacing: -0.04em;
26 color: var(--hg-fg);
27 z-index: 5;
28 pointer-events: none;
29 }
30 .gooey-stage {
31 position: absolute;
32 inset: 0;
33 filter: url(#gooey-filter);
34 }
35 .ball {
36 position: absolute;
37 border-radius: 50%;
38 background: var(--hg-violet-2);
39 top: 50%;
40 left: 50%;
41 will-change: transform;
42 opacity: 0;
43 }
44 .ball.a {
45 width: 280px;
46 height: 280px;
47 background: #7c3aed;
48 }
49 .ball.b {
50 width: 240px;
51 height: 240px;
52 background: #a855f7;
53 }
54 .ball.c {
55 width: 200px;
56 height: 200px;
57 background: #d946ef;
58 }
59 .ball.d {
60 width: 320px;
61 height: 320px;
62 background: #8b5cf6;
63 }
64 .ball.e {
65 width: 180px;
66 height: 180px;
67 background: #c084fc;
68 }
69 </style>
70 <svg style="position: absolute; width: 0; height: 0">
71 <defs>
72 <filter id="gooey-filter">
73 <feGaussianBlur in="SourceGraphic" stdDeviation="20" result="blur" />
74 <feColorMatrix
75 in="blur"
76 mode="matrix"
77 values="
78 1 0 0 0 0
79 0 1 0 0 0
80 0 0 1 0 0
81 0 0 0 22 -10"
82 result="gooey"
83 />
84 <feComposite in="SourceGraphic" in2="gooey" operator="atop" />
85 </filter>
86 </defs>
87 </svg>
88
89 <div class="gooey-stage">
90 <div class="ball a" id="ballA"></div>
91 <div class="ball b" id="ballB"></div>
92 <div class="ball c" id="ballC"></div>
93 <div class="ball d" id="ballD"></div>
94 <div class="ball e" id="ballE"></div>
95 </div>
96
97 <div class="hero">GOOEY</div>
98 <script>
99 window.__timelines = window.__timelines || {};
100 const tl = gsap.timeline({ paused: true });
101
102 // Initial: all balls collapsed at center
103 ["#ballA", "#ballB", "#ballC", "#ballD", "#ballE"].forEach((id) => {
104 tl.set(id, { xPercent: -50, yPercent: -50, scale: 0, opacity: 0 }, 0);
105 });
106 // Spawn outward
107 tl.to(
108 "#ballA",
109 {
110 xPercent: -50 - 120,
111 yPercent: -50 + 20,
112 scale: 1,
113 opacity: 1,
114 duration: 0.5,
115 ease: "back.out(1.6)",
116 },
117 0.15,
118 );
119 tl.to(
120 "#ballB",
121 {
122 xPercent: -50 + 100,
123 yPercent: -50 + 50,
124 scale: 1,
125 opacity: 1,
126 duration: 0.55,
127 ease: "back.out(1.6)",
128 },
129 0.2,
130 );
131 tl.to(
132 "#ballC",
133 {
134 xPercent: -50 + 30,
135 yPercent: -50 - 80,
136 scale: 1,
137 opacity: 1,
138 duration: 0.55,
139 ease: "back.out(1.6)",
140 },
141 0.25,
142 );
143 tl.to(
144 "#ballD",
145 {
146 xPercent: -50 - 50,
147 yPercent: -50 - 30,
148 scale: 1,
149 opacity: 1,
150 duration: 0.55,
151 ease: "back.out(1.6)",
152 },
153 0.3,
154 );
155 tl.to(
156 "#ballE",
157 {
158 xPercent: -50 + 80,
159 yPercent: -50 - 40,
160 scale: 1,
161 opacity: 1,
162 duration: 0.55,
163 ease: "back.out(1.6)",
164 },
165 0.18,
166 );
167
168 // Idle drift
169 tl.to(
170 "#ballA",
171 { xPercent: "+=20", yPercent: "+=12", duration: 1.0, ease: "sine.inOut" },
172 0.7,
173 );
174 tl.to(
175 "#ballB",
176 { xPercent: "-=18", yPercent: "-=10", duration: 1.0, ease: "sine.inOut" },
177 0.7,
178 );
179 tl.to(
180 "#ballC",
181 { xPercent: "-=15", yPercent: "+=20", duration: 1.0, ease: "sine.inOut" },
182 0.7,
183 );
184 tl.to(
185 "#ballD",
186 { xPercent: "+=25", yPercent: "+=8", duration: 1.0, ease: "sine.inOut" },
187 0.7,
188 );
189 tl.to(
190 "#ballE",
191 { xPercent: "-=22", yPercent: "+=18", duration: 1.0, ease: "sine.inOut" },
192 0.7,
193 );
194
195 // Reveal text behind
196 tl.fromTo(
197 ".hero",
198 { opacity: 0, scale: 0.95 },
199 { opacity: 1, scale: 1, duration: 0.5, ease: "power3.out" },
200 0.6,
201 );
202
203 window.__timelines["gooey-metaball"] = tl;
204 </script>
205 </div>
206</template>