├── .DS_Store
├── .gitattributes
├── .gitignore
├── LICENSE
├── README.md
├── css
└── base.css
├── favicon.ico
├── img
├── .DS_Store
├── 1.jpg
├── 10.jpg
├── 11.jpg
├── 12.jpg
├── 13.jpg
├── 14.jpg
├── 15.jpg
├── 16.jpg
├── 17.jpg
├── 18.jpg
├── 19.jpg
├── 2.jpg
├── 20.jpg
├── 21.jpg
├── 3.jpg
├── 4.jpg
├── 5.jpg
├── 6.jpg
├── 7.jpg
├── 8.jpg
└── 9.jpg
├── index.html
└── js
├── ScrollTrigger.min.js
├── filter1.js
├── filter2.js
├── filter3.js
├── filter4.js
├── filter5.js
├── filter6.js
├── filter7.js
├── gsap.min.js
├── imagesloaded.pkgd.min.js
├── lenis.min.js
├── main.js
├── smoothscroll.js
└── utils.js
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/.DS_Store
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | .cache
3 | .parcel-cache
4 | package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2009 - 2024 [Codrops](https://tympanus.net/codrops)
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Scroll-based SVG Filter Animations on Text
2 |
3 | A small set of scroll-based SVG filter animations on HTML text.
4 |
5 | 
6 |
7 | [Article on Codrops](https://tympanus.net/codrops/?p=80141)
8 |
9 | [Demo](https://tympanus.net/Development/OnScrollSVGFilterText)
10 |
11 | ## Installation
12 |
13 | Run this demo on a [local server](https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Tools_and_setup/set_up_a_local_testing_server).
14 |
15 | ## Credits
16 |
17 | - Images generated with [Midjourney](https://midjourney.com)
18 |
19 | ## Misc
20 |
21 | Follow Codrops: [X](http://www.X.com/codrops), [Facebook](http://www.facebook.com/codrops), [GitHub](https://github.com/codrops), [Instagram](https://www.instagram.com/codropsss/)
22 |
23 | ## License
24 | [MIT](LICENSE)
25 |
26 | Made with :blue_heart: by [Codrops](http://www.codrops.com)
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/css/base.css:
--------------------------------------------------------------------------------
1 | *,
2 | *::after,
3 | *::before {
4 | box-sizing: border-box;
5 | }
6 |
7 | :root {
8 | font-size: 12px;
9 | --color-text: #cfc9cb;
10 | --color-text-1: #9dcbce;
11 | --color-text-2: #d79fb0;
12 | --color-text-3: #167975;
13 | --color-bg: #282828;
14 | --color-link: #6e817b;
15 | --color-link-hover: #fff;
16 | --page-padding: 1rem;
17 | }
18 |
19 | html, body {
20 | width: 100vw;
21 | overflow-x: hidden;
22 | }
23 |
24 | body {
25 | margin: 0;
26 | color: var(--color-text);
27 | background-color: var(--color-bg);
28 | font-family: "monotype-grotesque", sans-serif;
29 | -webkit-font-smoothing: antialiased;
30 | -moz-osx-font-smoothing: grayscale;
31 | }
32 |
33 | /* Page Loader */
34 | .loading::before,
35 | .loading::after {
36 | content: '';
37 | position: fixed;
38 | z-index: 1000;
39 | }
40 |
41 | .loading::before {
42 | top: 0;
43 | left: 0;
44 | width: 100%;
45 | height: 100%;
46 | background: var(--color-bg);
47 | }
48 |
49 | .loading::after {
50 | top: 50%;
51 | left: 50%;
52 | width: 60px;
53 | height: 60px;
54 | margin: -30px 0 0 -30px;
55 | opacity: 0.4;
56 | background: var(--color-link);
57 | animation: loaderAnim 0.7s linear infinite alternate forwards;
58 |
59 | }
60 |
61 | @keyframes loaderAnim {
62 | to {
63 | opacity: 1;
64 | transform: scale3d(0.7,0.7,1);
65 | }
66 | }
67 |
68 | a {
69 | text-decoration: underline;
70 | color: var(--color-link);
71 | outline: none;
72 | cursor: pointer;
73 | }
74 |
75 | a:hover {
76 | text-decoration: none;
77 | color: var(--color-link-hover);
78 | outline: none;
79 | }
80 |
81 | /* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */
82 | a:focus {
83 | /* Provide a fallback style for browsers
84 | that don't support :focus-visible */
85 | outline: none;
86 | }
87 |
88 | a:focus-visible {
89 | /* Draw a very noticeable focus style for
90 | keyboard-focus on browsers that do support
91 | :focus-visible */
92 | outline: 2px solid red;
93 | }
94 |
95 | main {
96 | position: relative;
97 | }
98 |
99 | main::before {
100 | content: 'Trapped';
101 | font-family: "the-seasons", sans-serif;
102 | font-weight: 400;
103 | text-transform: uppercase;
104 | position: absolute;
105 | top: 30vh;
106 | z-index: -1;
107 | left: -1rem;
108 | color: rgba(0,0,0,0.15);
109 | pointer-events: none;
110 | font-size: 25vw;
111 | }
112 |
113 | .frame {
114 | z-index: 99;
115 | color: var(--color-link);
116 | padding: var(--page-padding);
117 | position: relative;
118 | display: grid;
119 | width: 100%;
120 | grid-row-gap: 1rem;
121 | grid-column-gap: 2rem;
122 | pointer-events: none;
123 | justify-items: start;
124 | text-transform: uppercase;
125 | }
126 |
127 | .frame--header {
128 | margin-bottom: 10vh;
129 | grid-template-columns: auto;
130 | grid-template-areas: 'title' 'links' 'sponsor';
131 | align-items: start;
132 | }
133 |
134 | .frame--footer {
135 | grid-template-columns: auto auto 1fr;
136 | justify-content: space-between;
137 | }
138 |
139 | .frame--footer a:last-child {
140 | justify-self: end;
141 | }
142 |
143 | .frame a {
144 | pointer-events: auto;
145 | font-weight: 700;
146 | }
147 |
148 | .frame__title {
149 | grid-area: title;
150 | font-size: inherit;
151 | margin: 0;
152 | }
153 |
154 | .frame__links {
155 | grid-area: links;
156 | display: flex;
157 | gap: 1rem;
158 | }
159 |
160 | .content {
161 | padding: var(--page-padding);
162 | display: grid;
163 | position: relative;
164 | font-size: clamp(1.5rem, 7vw, 3.5rem);
165 | }
166 |
167 | .hidden {
168 | width: 0;
169 | height: 0;
170 | position: absolute;
171 | pointer-events: none;
172 | }
173 |
174 | .content--full {
175 | min-height: 100vh;
176 | display: grid;
177 | }
178 |
179 | .content--intro {
180 | height: 100vh;
181 | display: grid;
182 | align-items: end;
183 | align-content: end;
184 | }
185 |
186 | .content p {
187 | margin: 0;
188 | font-family: "mencken-std-head-narrow", sans-serif;
189 | font-weight: 400;
190 | line-height: 0.95;
191 | }
192 |
193 | .content h2 {
194 | margin: 0;
195 | line-height: 1;
196 | align-self: center;
197 | }
198 |
199 | .font-1 {
200 | font-family: "anisette-std", sans-serif;
201 | font-weight: 700;
202 | text-transform: uppercase;
203 | }
204 |
205 | .font-2 {
206 | font-family: "the-seasons", sans-serif;
207 | font-weight: 400;
208 | text-transform: uppercase;
209 | }
210 |
211 | .start {
212 | justify-self: start;
213 | }
214 |
215 | .end {
216 | justify-self: end;
217 | }
218 |
219 | .center {
220 | justify-self: center;
221 | }
222 |
223 | .spaced {
224 | margin: 20vh auto;
225 | }
226 |
227 | .size-small {
228 | font-size: clamp(1.5rem, 10vw, 8rem);
229 | }
230 |
231 | .size-medium {
232 | font-size: clamp(1.75rem, 15vw, 10rem);
233 | }
234 |
235 | .size-large {
236 | font-size: clamp(2rem,16vw,16rem);
237 | }
238 |
239 | .size-xlarge {
240 | font-size: clamp(2rem,22vw,20rem);
241 | }
242 |
243 | .color-1 {
244 | color: var(--color-text-1);
245 | }
246 |
247 | .color-2 {
248 | color: var(--color-text-2);
249 | }
250 |
251 | .color-3 {
252 | color: var(--color-text-3);
253 | }
254 |
255 | .blendmode-1 {
256 | mix-blend-mode: plus-lighter;
257 | }
258 |
259 | .replay {
260 | border: 0;
261 | background: none;
262 | color: var(--color-text-1);
263 | font-family: "mencken-std-head-narrow", sans-serif;
264 | font-weight: 400;
265 | text-transform: uppercase;
266 | font-size: 2rem;
267 | align-self: start;
268 | cursor: pointer;
269 | margin: 0 5vw;
270 | padding: 1rem 1rem;
271 | position: relative;
272 | }
273 |
274 | .replay::before {
275 | content: '';
276 | position: absolute;
277 | top: 50%;
278 | width: 100%;
279 | aspect-ratio: 1;
280 | border: 1px solid;
281 | transform: translate3d(-50%, -50%, 0) rotateZ(45deg);
282 | border-radius: 10px;
283 | left: 50%;
284 | box-shadow: 10px 10px 0 black, 11px 11px 0 currentColor;
285 | }
286 |
287 | .replay:hover {
288 | color: var(--color-text-2);
289 | }
290 |
291 | .replay:active {
292 | color: var(--color-text-2);
293 | transform: translate3d(0, 5px, 0);
294 | }
295 |
296 | .replay:active::before {
297 | box-shadow: 6px 6px 0 black, 7px 7px 0 currentColor;
298 | }
299 |
300 | .deco {
301 | display: grid;
302 | width: 100%;
303 | height: 100%;
304 | position: absolute;
305 | gap: 2rem;
306 | top: 10rem;
307 | left: 0;
308 | z-index: -1;
309 | pointer-events: none;
310 | filter: brightness(0.6) contrast(0.9);
311 | grid-template-columns: repeat(3,auto);
312 | grid-template-rows: repeat(36,1fr);
313 | }
314 |
315 | .deco__item {
316 | grid-column: 3 / span 1;
317 | background-size: cover;
318 | width: auto;
319 | aspect-ratio: 2/3;
320 | max-width: 33vw;
321 | border-radius: 10px;
322 | }
323 |
324 | .deco__item:nth-child(2n) {
325 | max-width: 18vw;
326 | grid-column: 1 / span 3;
327 | }
328 |
329 | .deco__item:nth-child(3n) {
330 | max-width: 12vw;
331 | grid-column: 2 / span 2;
332 | }
333 |
334 | @media screen and (min-width: 53em) {
335 | body {
336 | --page-padding: 2rem 3rem;
337 | }
338 | .frame--header {
339 | position: absolute;
340 | top: 0;
341 | left: 0;
342 | width: 100%;
343 | gap: 3rem;
344 | grid-template-columns: auto auto 1fr;
345 | grid-template-areas: 'title links sponsor';
346 | }
347 | .deco {
348 | grid-template-columns: repeat(5,auto);
349 | }
350 | .deco__item {
351 | grid-column: 3 / span 1;
352 | max-width: 10vw;
353 | }
354 | .deco__item:nth-child(2n) {
355 | max-width: 25vw;
356 | grid-column: 5 / span 4;
357 | }
358 |
359 | .deco__item:nth-child(3n) {
360 | max-width: 10vw;
361 | grid-column: 4 / span 2;
362 | }
363 |
364 | .deco__item:nth-child(4n) {
365 | grid-column: 2 / span 3;
366 | max-width: 17vw;
367 | }
368 |
369 | .deco__item:nth-child(5n) {
370 | max-width: 12vw;
371 | grid-column: 2 / span 4;
372 | }
373 |
374 | .deco__item:nth-child(6n) {
375 | max-width: 30vw;
376 | margin-top: -10vh;
377 | grid-column: 4 / span 1;
378 | }
379 |
380 | .deco__item:nth-child(6n) {
381 | max-width: 20vw;
382 | margin-left: -10vw;
383 | grid-column: 5 / span 3;
384 | }
385 | }
386 |
387 | html.lenis, html.lenis body {
388 | height: auto;
389 | }
390 |
391 | .lenis.lenis-smooth {
392 | scroll-behavior: auto !important;
393 | }
394 |
395 | .lenis.lenis-smooth [data-lenis-prevent] {
396 | overscroll-behavior: contain;
397 | }
398 |
399 | .lenis.lenis-stopped {
400 | overflow: hidden;
401 | }
402 |
403 | .lenis.lenis-smooth iframe {
404 | pointer-events: none;
405 | }
406 |
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/favicon.ico
--------------------------------------------------------------------------------
/img/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/.DS_Store
--------------------------------------------------------------------------------
/img/1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/1.jpg
--------------------------------------------------------------------------------
/img/10.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/10.jpg
--------------------------------------------------------------------------------
/img/11.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/11.jpg
--------------------------------------------------------------------------------
/img/12.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/12.jpg
--------------------------------------------------------------------------------
/img/13.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/13.jpg
--------------------------------------------------------------------------------
/img/14.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/14.jpg
--------------------------------------------------------------------------------
/img/15.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/15.jpg
--------------------------------------------------------------------------------
/img/16.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/16.jpg
--------------------------------------------------------------------------------
/img/17.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/17.jpg
--------------------------------------------------------------------------------
/img/18.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/18.jpg
--------------------------------------------------------------------------------
/img/19.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/19.jpg
--------------------------------------------------------------------------------
/img/2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/2.jpg
--------------------------------------------------------------------------------
/img/20.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/20.jpg
--------------------------------------------------------------------------------
/img/21.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/21.jpg
--------------------------------------------------------------------------------
/img/3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/3.jpg
--------------------------------------------------------------------------------
/img/4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/4.jpg
--------------------------------------------------------------------------------
/img/5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/5.jpg
--------------------------------------------------------------------------------
/img/6.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/6.jpg
--------------------------------------------------------------------------------
/img/7.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/7.jpg
--------------------------------------------------------------------------------
/img/8.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/8.jpg
--------------------------------------------------------------------------------
/img/9.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/codrops/OnScrollSVGFilterText/93fbe0ed632af03722c3af9e01f4e3cb4524f104/img/9.jpg
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | On-Scroll SVG Filter Animations on Text | Codrops
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
86 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
The wavelength gently grows
140 | Coercive notions re-evolve
141 | A universe is trapped inside a tear
142 |
143 |
144 |
Wave
145 |
146 |
147 |
148 |
Shattered dreams of what could be
149 | The past and future blur into a line
150 |
151 |
152 |
Dreams
153 |
154 |
155 |
156 |
It resonates the core
157 | Creates unnatural laws
158 | Replaces love and happiness
159 | with fear
160 |
Unreal
161 |
162 |
163 |
164 |
Dissolve
165 | Reality's a fragile veil
166 | Illusions we’ve compiled
167 | Now unravel in the wind
168 |
169 |
170 |
Fear
171 |
172 |
173 |
174 |
How much deception can you take?
175 | How many lies will you create?
176 |
177 |
178 |
Deception
179 |
180 |
181 |
182 |
And they are breaking through
183 | They are breaking through
184 | We are losing control
185 |
186 |
187 |
Delete
188 |
189 |
Invisible to all
190 | The mind becomes a wall
191 | All of history deleted
192 | with one stroke
193 |
194 |
195 |
All of it
196 |
197 |
198 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
--------------------------------------------------------------------------------
/js/ScrollTrigger.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * ScrollTrigger 3.12.5
3 | * https://gsap.com
4 | *
5 | * @license Copyright 2024, GreenSock. All rights reserved.
6 | * Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
7 | * @author: Jack Doyle, jack@greensock.com
8 | */
9 |
10 | !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e=e||self).window=e.window||{})}(this,function(e){"use strict";function _defineProperties(e,t){for(var r=0;r=Math.abs(r)?t:r}function O(){(Ae=Ce.core.globals().ScrollTrigger)&&Ae.core&&function _integrate(){var e=Ae.core,r=e.bridge||{},t=e._scrollers,n=e._proxies;t.push.apply(t,Ie),n.push.apply(n,Le),Ie=t,Le=n,i=function _bridge(e,t){return r[e](t)}}()}function P(e){return Ce=e||r(),!Te&&Ce&&"undefined"!=typeof document&&document.body&&(Se=window,Pe=(ke=document).documentElement,Me=ke.body,t=[Se,ke,Pe,Me],Ce.utils.clamp,Be=Ce.core.context||function(){},Oe="onpointerenter"in Me?"pointer":"mouse",Ee=k.isTouch=Se.matchMedia&&Se.matchMedia("(hover: none), (pointer: coarse)").matches?1:"ontouchstart"in Se||0=o,n=Math.abs(t)>=o;S&&(r||n)&&S(se,e,t,me,ye),r&&(m&&0Math.abs(t)?"x":"y",ie=!0),"y"!==ae&&(me[2]+=e,se._vx.update(e,!0)),"x"!==ae&&(ye[2]+=t,se._vy.update(t,!0)),n?ee=ee||requestAnimationFrame(ff):ff()}function jf(e){if(!df(e,1)){var t=(e=M(e,s)).clientX,r=e.clientY,n=t-se.x,o=r-se.y,i=se.isDragging;se.x=t,se.y=r,(i||Math.abs(se.startX-t)>=a||Math.abs(se.startY-r)>=a)&&(h&&(re=!0),i||(se.isDragging=!0),hf(n,o),i||p&&p(se))}}function mf(e){return e.touches&&1=e)return a[n];return a[n-1]}for(n=a.length,e+=r;n--;)if(a[n]<=e)return a[n];return a[0]}:function(e,t,r){void 0===r&&(r=.001);var n=i(e);return!t||Math.abs(n-e)r&&(n*=t/100),e=e.substr(0,r-1)),e=n+(e in H?H[e]*t:~e.indexOf("%")?parseFloat(e)*t/100:parseFloat(e)||0)}return e}function Db(e,t,r,n,o,i,a,s){var l=o.startColor,c=o.endColor,u=o.fontSize,f=o.indent,d=o.fontWeight,p=Xe.createElement("div"),g=La(r)||"fixed"===z(r,"pinType"),h=-1!==e.indexOf("scroller"),v=g?We:r,b=-1!==e.indexOf("start"),m=b?l:c,y="border-color:"+m+";font-size:"+u+";color:"+m+";font-weight:"+d+";pointer-events:none;white-space:nowrap;font-family:sans-serif,Arial;z-index:1000;padding:4px 8px;border-width:0;border-style:solid;";return y+="position:"+((h||s)&&g?"fixed;":"absolute;"),!h&&!s&&g||(y+=(n===Fe?q:I)+":"+(i+parseFloat(f))+"px;"),a&&(y+="box-sizing:border-box;text-align:left;width:"+a.offsetWidth+"px;"),p._isStart=b,p.setAttribute("class","gsap-marker-"+e+(t?" marker-"+t:"")),p.style.cssText=y,p.innerText=t||0===t?e+"-"+t:e,v.children[0]?v.insertBefore(p,v.children[0]):v.appendChild(p),p._offset=p["offset"+n.op.d2],X(p,0,n,b),p}function Ib(){return 34We.clientWidth)||(Ie.cache++,v?D=D||requestAnimationFrame(Z):Z(),st||U("scrollStart"),st=at())}function Kb(){y=Ne.innerWidth,m=Ne.innerHeight}function Lb(){Ie.cache++,je||h||Xe.fullscreenElement||Xe.webkitFullscreenElement||b&&y===Ne.innerWidth&&!(Math.abs(Ne.innerHeight-m)>.25*Ne.innerHeight)||c.restart(!0)}function Ob(){return xb(ne,"scrollEnd",Ob)||Pt(!0)}function Rb(e){for(var t=0;tt,n=e._startClamp&&e.start>=t;(r||n)&&e.setPositions(n?t-1:e.start,r?Math.max(n?t:e.start+1,t):e.end,!0)}),Zb(!1),et=0,r.forEach(function(e){return e&&e.render&&e.render(-1)}),Ie.forEach(function(e){Ta(e)&&(e.smooth&&requestAnimationFrame(function(){return e.target.style.scrollBehavior="smooth"}),e.rec&&e(e.rec))}),Tb(w,1),c.pause(),kt++,Z(rt=2),Tt.forEach(function(e){return Ta(e.vars.onRefresh)&&e.vars.onRefresh(e)}),rt=ne.isRefreshing=!1,U("refresh")}else wb(ne,"scrollEnd",Ob)},Q=0,Mt=1,Z=function _updateAll(e){if(2===e||!rt&&!S){ne.isUpdating=!0,ot&&ot.update(0);var t=Tt.length,r=at(),n=50<=r-R,o=t&&Tt[0].scroll();if(Mt=o=Qa(be,he)){if(ie&&Ae()&&!de)for(i=ie.parentNode;i&&i!==We;)i._pinOffset&&(B-=i._pinOffset,q-=i._pinOffset),i=i.parentNode}else o=mb(ae),s=he===Fe,a=Ae(),G=parseFloat(j(he.a))+_,!y&&1=q})},Te.update=function(e,t,r){if(!de||r||e){var n,o,i,a,s,l,c,u=!0===rt?re:Te.scroll(),f=e?0:(u-B)/N,d=f<0?0:1u+(u-R)/(at()-Ke)*M&&(d=.9999)),d!==p&&Te.enabled){if(a=(s=(n=Te.isActive=!!d&&d<1)!=(!!p&&p<1))||!!d!=!!p,Te.direction=p=Qa(be,he),fe)if(e||!n&&!l)oc(ae,U);else{var g=wt(ae,!0),h=u-B;oc(ae,We,g.top+(he===Fe?h:0)+xt,g.left+(he===Fe?0:h)+xt)}Et(n||l?W:V),$&&d<1&&n||b(G+(1!==d||l?0:Q))}}else b(Ia(G+Q*d));!ue||A.tween||je||it||te.restart(!0),S&&(s||ce&&d&&(d<1||!tt))&&Ve(S.targets).forEach(function(e){return e.classList[n||ce?"add":"remove"](S.className)}),!T||ve||e||T(Te),a&&!je?(ve&&(c&&("complete"===i?O.pause().totalProgress(1):"reset"===i?O.restart(!0).pause():"restart"===i?O.restart(!0):O[i]()),T&&T(Te)),!s&&tt||(k&&s&&Xa(Te,k),xe[o]&&Xa(Te,xe[o]),ce&&(1===d?Te.kill(!1,1):xe[o]=0),s||xe[o=1===d?1:3]&&Xa(Te,xe[o])),pe&&!n&&Math.abs(Te.getVelocity())>(Ua(pe)?pe:2500)&&(Wa(Te.callbackAnimation),ee?ee.progress(1):Wa(O,"reverse"===i?1:!d,1))):ve&&T&&!je&&T(Te)}if(x){var v=de?u/de.duration()*(de._caScrollDist||0):u;y(v+(Y._isFlipped?1:0)),x(v)}C&&C(-u/de.duration()*(de._caScrollDist||0))}},Te.enable=function(e,t){Te.enabled||(Te.enabled=!0,wb(be,"resize",Lb),me||wb(be,"scroll",Jb),Se&&wb(ScrollTrigger,"refreshInit",Se),!1!==e&&(Te.progress=Oe=0,D=R=Me=Ae()),!1!==t&&Te.refresh())},Te.getTween=function(e){return e&&A?A.tween:ee},Te.setPositions=function(e,t,r,n){if(de){var o=de.scrollTrigger,i=de.duration(),a=o.end-o.start;e=o.start+a*e/i,t=o.start+a*t/i}Te.refresh(!1,!1,{start:Da(e,r&&!!Te._startClamp),end:Da(t,r&&!!Te._endClamp)},n),Te.update()},Te.adjustPinSpacing=function(e){if(Z&&e){var t=Z.indexOf(he.d)+1;Z[t]=parseFloat(Z[t])+e+xt,Z[1]=parseFloat(Z[1])+e+xt,Et(Z)}},Te.disable=function(e,t){if(Te.enabled&&(!1!==e&&Te.revert(!0,!0),Te.enabled=Te.isActive=!1,t||ee&&ee.pause(),re=0,n&&(n.uncache=1),Se&&xb(ScrollTrigger,"refreshInit",Se),te&&(te.pause(),A.tween&&A.tween.kill()&&(A.tween=0)),!me)){for(var r=Tt.length;r--;)if(Tt[r].scroller===be&&Tt[r]!==Te)return;xb(be,"resize",Lb),me||xb(be,"scroll",Jb)}},Te.kill=function(e,t){Te.disable(e,t),ee&&!t&&ee.kill(),a&&delete St[a];var r=Tt.indexOf(Te);0<=r&&Tt.splice(r,1),r===Qe&&0i&&(b()>i?a.progress(1)&&b(i):a.resetTo("scrollY",i))}Va(e)||(e={}),e.preventDefault=e.isNormalizer=e.allowClicks=!0,e.type||(e.type="wheel,touch"),e.debounce=!!e.debounce,e.id=e.id||"normalizer";var n,i,l,o,a,c,u,s,f=e.normalizeScrollX,t=e.momentum,r=e.allowNestedScroll,d=e.onRelease,p=J(e.target)||Je,g=He.core.globals().ScrollSmoother,h=g&&g.get(),v=E&&(e.content&&J(e.content)||h&&!1!==e.content&&!h.smooth()&&h.content()),b=K(p,Fe),m=K(p,Ye),y=1,x=(k.isTouch&&Ne.visualViewport?Ne.visualViewport.scale*Ne.visualViewport.width:Ne.outerWidth)/Ne.innerWidth,w=0,_=Ta(t)?function(){return t(n)}:function(){return t||2.8},C=xc(p,e.type,!0,r),T=Ha,S=Ha;return v&&He.set(v,{y:"+=0"}),e.ignoreCheck=function(e){return E&&"touchmove"===e.type&&function ignoreDrag(){if(o){requestAnimationFrame(zq);var e=Ia(n.deltaY/2),t=S(b.v-e);if(v&&t!==b.v+b.offset){b.offset=t-b.v;var r=Ia((parseFloat(v&&v._gsap.y)||0)-b.offset);v.style.transform="matrix3d(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, "+r+", 0, 1)",v._gsap.y=r+"px",b.cacheID=Ie.cache,Z()}return!0}b.offset&&Dq(),o=!0}()||1.05=i||i-1<=r)&&He.to({},{onUpdate:Jq,duration:o})}else s.restart(!0);d&&d(e)},e.onWheel=function(){a._ts&&a.pause(),1e3 {
30 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
31 | },
32 | scrollTrigger: {
33 | trigger: text, // Trigger the animation when the text enters the viewport
34 | start: 'center bottom'
35 | }
36 | })
37 | .to(primitiveValues, {
38 | startAt: { stdDeviation: 50 },
39 | stdDeviation: 0
40 | }, 0)
41 | .to(text, {
42 | startAt: {
43 | opacity: 0
44 | },
45 | opacity: 1
46 | }, 0);
47 |
48 | // Find the corresponding replay button (assumes button is the next sibling)
49 | const replayButton = text.nextElementSibling;
50 |
51 | // Add click event listener to the replay button
52 | if (replayButton && replayButton.classList.contains('replay')) {
53 | replayButton.addEventListener('click', () => {
54 | // Restart the timeline when the button is clicked
55 | animationTimeline.restart();
56 | });
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/js/filter2.js:
--------------------------------------------------------------------------------
1 | export default function(text) {
2 | // Get the filter ID from the element's data attribute
3 | const filterId = text.getAttribute('data-filter');
4 |
5 | // Select the necessary SVG filter elements
6 | const feBlur = document.querySelector(`#${filterId} feGaussianBlur`);
7 | const feTurbulence = document.querySelector(`#${filterId} feTurbulence`);
8 | const feDisplacementMap = document.querySelector(`#${filterId} feDisplacementMap`);
9 |
10 | // Check if required elements exist
11 | if (!feBlur || !feDisplacementMap) {
12 | console.warn(`Filter with ID ${filterId} not found for element`, text);
13 | return;
14 | }
15 |
16 | // Apply the filter to the text element
17 | text.style.filter = `url(#${filterId})`;
18 |
19 | // Object to store the values for blur, scale, and turbulence frequency
20 | let primitiveValues = { stdDeviation: 0, scale: 0, baseFrequency: 0 };
21 |
22 | // Set initial opacity to 0
23 | gsap.set(text, { opacity: 0 });
24 |
25 | // Create the animation timeline
26 | const animationTimeline = gsap.timeline({
27 | defaults: {
28 | duration: 2,
29 | ease: 'expo',
30 | },
31 | // On every update, set the appropriate attributes in the SVG filters
32 | onUpdate: () => {
33 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
34 | feDisplacementMap.setAttribute('scale', primitiveValues.scale);
35 | feTurbulence.setAttribute('baseFrequency', primitiveValues.baseFrequency);
36 | },
37 | scrollTrigger: {
38 | trigger: text, // Trigger the animation when the text enters the viewport
39 | start: 'center bottom'
40 | }
41 | })
42 | .to(primitiveValues, {
43 | startAt: {
44 | stdDeviation: 20, // Start with a strong blur
45 | scale: 100, // Start with a high displacement
46 | baseFrequency: 0.1 // Start with a higher turbulence frequency
47 | },
48 | stdDeviation: 0,
49 | scale: 0,
50 | baseFrequency: 0.05
51 | }, 0)
52 | .to(text, {
53 | startAt: {
54 | opacity: 0
55 | },
56 | opacity: 1
57 | }, 0);
58 |
59 | // Find the corresponding replay button (assumes button is the next sibling)
60 | const replayButton = text.nextElementSibling;
61 |
62 | // Add click event listener to the replay button
63 | if (replayButton && replayButton.classList.contains('replay')) {
64 | replayButton.addEventListener('click', () => {
65 | // Restart the timeline when the button is clicked
66 | animationTimeline.restart();
67 | });
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/js/filter3.js:
--------------------------------------------------------------------------------
1 | export default function(text) {
2 | // Get the filter ID from the element's data attribute
3 | const filterId = text.getAttribute('data-filter');
4 |
5 | // Select the necessary SVG filter elements
6 | const feBlur = document.querySelector(`#${filterId} feGaussianBlur`);
7 | const feDisplacementMap = document.querySelector(`#${filterId} feDisplacementMap`);
8 |
9 | // Check if required elements exist
10 | if (!feBlur || !feDisplacementMap) {
11 | console.warn(`Filter with ID ${filterId} not found for element`, text);
12 | return;
13 | }
14 |
15 | // Apply the filter to the text element
16 | text.style.filter = `url(#${filterId})`;
17 |
18 | // Object to store the values for blur and displacement
19 | let primitiveValues = { stdDeviation: 0, scale: 0 };
20 |
21 | // Set initial opacity to 0
22 | gsap.set(text, { opacity: 0 });
23 |
24 | // Create the animation timeline
25 | const animationTimeline = gsap.timeline({
26 | defaults: {
27 | duration: 2,
28 | ease: 'power4',
29 | },
30 | // On every update, set the appropriate attributes in the SVG filters
31 | onUpdate: () => {
32 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
33 | feDisplacementMap.setAttribute('scale', primitiveValues.scale);
34 | },
35 | scrollTrigger: {
36 | trigger: text, // Trigger the animation when the text enters the viewport
37 | start: 'center bottom',
38 | }
39 | })
40 | .to(primitiveValues, {
41 | startAt: { stdDeviation: 40, scale: 150 }, // Start with a strong blur and high displacement
42 | stdDeviation: 0,
43 | scale: 0
44 | }, 0)
45 | .to(text, {
46 | startAt: {
47 | opacity: 0,
48 | scale: 0.9
49 | },
50 | opacity: 1,
51 | scale: 1
52 | }, 0);
53 |
54 | // Find the corresponding replay button (assumes button is the next sibling)
55 | const replayButton = text.nextElementSibling;
56 |
57 | // Add click event listener to the replay button
58 | if (replayButton && replayButton.classList.contains('replay')) {
59 | replayButton.addEventListener('click', () => {
60 | // Restart the timeline when the button is clicked
61 | animationTimeline.restart();
62 | });
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/js/filter4.js:
--------------------------------------------------------------------------------
1 | export default function(text) {
2 | // Get the filter ID from the element's data attribute
3 | const filterId = text.getAttribute('data-filter');
4 |
5 | // Select the necessary SVG filter elements
6 | const feBlur = document.querySelector(`#${filterId} feGaussianBlur`);
7 | const feDisplacementMap = document.querySelector(`#${filterId} feDisplacementMap`);
8 |
9 | // Check if required elements exist
10 | if (!feBlur || !feDisplacementMap) {
11 | console.warn(`Filter with ID ${filterId} not found for element`, text);
12 | return;
13 | }
14 |
15 | // Apply the filter to the text element
16 | text.style.filter = `url(#${filterId})`;
17 |
18 | // Object to store the values for blur and displacement
19 | let primitiveValues = { stdDeviation: 0, scale: 0 };
20 |
21 | // Set initial opacity to 0
22 | gsap.set(text, { opacity: 0 });
23 |
24 | // Create the animation timeline
25 | const animationTimeline = gsap.timeline({
26 | defaults: {
27 | duration: 2,
28 | ease: 'expo',
29 | },
30 | // On every update, set the appropriate attributes in the SVG filters
31 | onUpdate: () => {
32 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
33 | feDisplacementMap.setAttribute('scale', primitiveValues.scale);
34 | },
35 | scrollTrigger: {
36 | trigger: text, // Trigger the animation when the text enters the viewport
37 | start: 'center bottom',
38 | }
39 | })
40 | .to(primitiveValues, {
41 | startAt: { stdDeviation: 70, scale: 200 }, // Start with a strong blur and high displacement
42 | stdDeviation: 0,
43 | scale: 0
44 | }, 0)
45 | .to(text, {
46 | startAt: {
47 | opacity: 0
48 | },
49 | opacity: 1
50 | }, 0);
51 |
52 | // Find the corresponding replay button (assumes button is the next sibling)
53 | const replayButton = text.nextElementSibling;
54 |
55 | // Add click event listener to the replay button
56 | if (replayButton && replayButton.classList.contains('replay')) {
57 | replayButton.addEventListener('click', () => {
58 | // Restart the timeline when the button is clicked
59 | animationTimeline.restart();
60 | });
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/js/filter5.js:
--------------------------------------------------------------------------------
1 | export default function(text) {
2 | // Get the filter ID from the element's data attribute
3 | const filterId = text.getAttribute('data-filter');
4 |
5 | // Select the necessary SVG filter elements
6 | const feBlur = document.querySelector(`#${filterId} feGaussianBlur`);
7 | const feDisplacementMap = document.querySelector(`#${filterId} feDisplacementMap`);
8 |
9 | // Check if required elements exist
10 | if (!feBlur || !feDisplacementMap) {
11 | console.warn(`Filter with ID ${filterId} not found for element`, text);
12 | return;
13 | }
14 |
15 | // Apply the filter to the text element
16 | text.style.filter = `url(#${filterId})`;
17 |
18 | // Object to store the values for blur and displacement
19 | let primitiveValues = { stdDeviation: 0, scale: 0 };
20 |
21 | // Set initial opacity to 0
22 | gsap.set(text, { opacity: 0 });
23 |
24 | // Create the animation timeline
25 | const animationTimeline = gsap.timeline({
26 | defaults: {
27 | duration: 1.7,
28 | ease: 'expo',
29 | },
30 | // On every update, set the appropriate attributes in the SVG filters
31 | onUpdate: () => {
32 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
33 | feDisplacementMap.setAttribute('scale', primitiveValues.scale);
34 | },
35 | scrollTrigger: {
36 | trigger: text, // Trigger the animation when the text enters the viewport
37 | start: 'center bottom',
38 | }
39 | })
40 | .to(primitiveValues, {
41 | startAt: { stdDeviation: 40, scale: 100 }, // Start with a strong blur and high displacement
42 | stdDeviation: 0,
43 | scale: 0
44 | }, 0)
45 | .to(text, {
46 | startAt: {
47 | opacity: 0,
48 | scale: .6
49 | },
50 | opacity: 1,
51 | scale: 1
52 | }, 0);
53 |
54 | // Find the corresponding replay button (assumes button is the next sibling)
55 | const replayButton = text.nextElementSibling;
56 |
57 | // Add click event listener to the replay button
58 | if (replayButton && replayButton.classList.contains('replay')) {
59 | replayButton.addEventListener('click', () => {
60 | // Restart the timeline when the button is clicked
61 | animationTimeline.restart();
62 | });
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/js/filter6.js:
--------------------------------------------------------------------------------
1 | export default function(text) {
2 | // Get the filter ID from the element's data attribute
3 | const filterId = text.getAttribute('data-filter');
4 |
5 | // Select the necessary SVG filter elements
6 | const feBlur = document.querySelector(`#${filterId} feGaussianBlur`);
7 | const feTurbulence = document.querySelector(`#${filterId} feTurbulence`);
8 | const feDisplacementMap = document.querySelector(`#${filterId} feDisplacementMap`);
9 |
10 | // Check if required elements exist
11 | if (!feBlur || !feDisplacementMap) {
12 | console.warn(`Filter with ID ${filterId} not found for element`, text);
13 | return;
14 | }
15 |
16 | // Apply the filter to the text element
17 | text.style.filter = `url(#${filterId})`;
18 |
19 | // Object to store the values for blur, scale, and turbulence frequency
20 | let primitiveValues = { stdDeviation: 0, scale: 0, baseFrequency: 0 };
21 |
22 | // Set initial opacity to 0
23 | gsap.set(text, { opacity: 0 });
24 |
25 | // Create the animation timeline
26 | const animationTimeline = gsap.timeline({
27 | defaults: {
28 | duration: 2,
29 | ease: 'expo',
30 | },
31 | // On every update, set the appropriate attributes in the SVG filters
32 | onUpdate: () => {
33 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
34 | feDisplacementMap.setAttribute('scale', primitiveValues.scale);
35 | feTurbulence.setAttribute('baseFrequency', primitiveValues.baseFrequency);
36 | },
37 | scrollTrigger: {
38 | trigger: text, // Trigger the animation when the text enters the viewport
39 | start: 'center bottom'
40 | }
41 | })
42 | .to(primitiveValues, {
43 | startAt: {
44 | stdDeviation: 90,
45 | scale: 300,
46 | baseFrequency: 0.1
47 | },
48 | stdDeviation: 0,
49 | scale: 0,
50 | baseFrequency: 0.01
51 | }, 0)
52 | .to(text, {
53 | startAt: {
54 | opacity: 0,
55 | scaleX: 2.4
56 | },
57 | opacity: 1,
58 | scaleX: 1
59 | }, 0);
60 |
61 | // Find the corresponding replay button (assumes button is the next sibling)
62 | const replayButton = text.nextElementSibling;
63 |
64 | // Add click event listener to the replay button
65 | if (replayButton && replayButton.classList.contains('replay')) {
66 | replayButton.addEventListener('click', () => {
67 | // Restart the timeline when the button is clicked
68 | animationTimeline.restart();
69 | });
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/js/filter7.js:
--------------------------------------------------------------------------------
1 | export default function(text) {
2 | // Get the filter ID from the element's data attribute
3 | const filterId = text.getAttribute('data-filter');
4 |
5 | // Select the necessary SVG filter elements
6 | const feBlur = document.querySelector(`#${filterId} feGaussianBlur`);
7 | const feDisplacementMap = document.querySelector(`#${filterId} feDisplacementMap`);
8 |
9 | // Check if required elements exist
10 | if (!feBlur || !feDisplacementMap) {
11 | console.warn(`Filter with ID ${filterId} not found for element`, text);
12 | return;
13 | }
14 |
15 | // Apply the filter to the text element
16 | text.style.filter = `url(#${filterId})`;
17 |
18 | // Object to store the values for blur and displacement
19 | let primitiveValues = { stdDeviation: 0, scale: 0 };
20 |
21 | // Set initial opacity to 0
22 | gsap.set(text, { opacity: 0 });
23 |
24 | // Create the animation timeline
25 | const animationTimeline = gsap.timeline({
26 | defaults: {
27 | duration: 1.6,
28 | ease: 'expo',
29 | },
30 | // On every update, set the appropriate attributes in the SVG filters
31 | onUpdate: () => {
32 | feBlur.setAttribute('stdDeviation', primitiveValues.stdDeviation);
33 | feDisplacementMap.setAttribute('scale', primitiveValues.scale);
34 | },
35 | scrollTrigger: {
36 | trigger: text, // Trigger the animation when the text enters the viewport
37 | start: 'center bottom',
38 | }
39 | })
40 | .to(primitiveValues, {
41 | startAt: { stdDeviation: 35, scale: 250 }, // Start with a strong blur and high displacement
42 | stdDeviation: 0,
43 | scale: 0
44 | }, 0)
45 | .to(text, {
46 | duration: 1.3,
47 | startAt: {
48 | opacity: 0,
49 | scale: 0.8,
50 | yPercent: 20
51 | },
52 | opacity: 1,
53 | scale: 1,
54 | yPercent: 0
55 | }, 0);
56 |
57 | // Find the corresponding replay button (assumes button is the next sibling)
58 | const replayButton = text.nextElementSibling;
59 |
60 | // Add click event listener to the replay button
61 | if (replayButton && replayButton.classList.contains('replay')) {
62 | replayButton.addEventListener('click', () => {
63 | // Restart the timeline when the button is clicked
64 | animationTimeline.restart();
65 | });
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/js/gsap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * GSAP 3.12.5
3 | * https://gsap.com
4 | *
5 | * @license Copyright 2024, GreenSock. All rights reserved.
6 | * Subject to the terms at https://gsap.com/standard-license or for Club GSAP members, the agreement issued with that membership.
7 | * @author: Jack Doyle, jack@greensock.com
8 | */
9 |
10 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?e(exports):"function"==typeof define&&define.amd?define(["exports"],e):e((t=t||self).window=t.window||{})}(this,function(e){"use strict";function _inheritsLoose(t,e){t.prototype=Object.create(e.prototype),(t.prototype.constructor=t).__proto__=e}function _assertThisInitialized(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}function r(t){return"string"==typeof t}function s(t){return"function"==typeof t}function t(t){return"number"==typeof t}function u(t){return void 0===t}function v(t){return"object"==typeof t}function w(t){return!1!==t}function x(){return"undefined"!=typeof window}function y(t){return s(t)||r(t)}function P(t){return(i=yt(t,ot))&&ze}function Q(t,e){return console.warn("Invalid property",t,"set to",e,"Missing plugin? gsap.registerPlugin()")}function R(t,e){return!e&&console.warn(t)}function S(t,e){return t&&(ot[t]=e)&&i&&(i[t]=e)||ot}function T(){return 0}function ea(t){var e,r,i=t[0];if(v(i)||s(i)||(t=[t]),!(e=(i._gsap||{}).harness)){for(r=gt.length;r--&&!gt[r].targetTest(i););e=gt[r]}for(r=t.length;r--;)t[r]&&(t[r]._gsap||(t[r]._gsap=new Vt(t[r],e)))||t.splice(r,1);return t}function fa(t){return t._gsap||ea(Mt(t))[0]._gsap}function ga(t,e,r){return(r=t[e])&&s(r)?t[e]():u(r)&&t.getAttribute&&t.getAttribute(e)||r}function ha(t,e){return(t=t.split(",")).forEach(e)||t}function ia(t){return Math.round(1e5*t)/1e5||0}function ja(t){return Math.round(1e7*t)/1e7||0}function ka(t,e){var r=e.charAt(0),i=parseFloat(e.substr(2));return t=parseFloat(t),"+"===r?t+i:"-"===r?t-i:"*"===r?t*i:t/i}function la(t,e){for(var r=e.length,i=0;t.indexOf(e[i])<0&&++ia;)s=s._prev;return s?(e._next=s._next,s._next=e):(e._next=t[r],t[r]=e),e._next?e._next._prev=e:t[i]=e,e._prev=s,e.parent=e._dp=t,e}function ya(t,e,r,i){void 0===r&&(r="_first"),void 0===i&&(i="_last");var n=e._prev,a=e._next;n?n._next=a:t[r]===e&&(t[r]=a),a?a._prev=n:t[i]===e&&(t[i]=n),e._next=e._prev=e.parent=null}function za(t,e){t.parent&&(!e||t.parent.autoRemoveChildren)&&t.parent.remove&&t.parent.remove(t),t._act=0}function Aa(t,e){if(t&&(!e||e._end>t._dur||e._start<0))for(var r=t;r;)r._dirty=1,r=r.parent;return t}function Ca(t,e,r,i){return t._startAt&&(L?t._startAt.revert(ht):t.vars.immediateRender&&!t.vars.autoRevert||t._startAt.render(e,!0,i))}function Ea(t){return t._repeat?Tt(t._tTime,t=t.duration()+t._rDelay)*t:0}function Ga(t,e){return(t-e._start)*e._ts+(0<=e._ts?0:e._dirty?e.totalDuration():e._tDur)}function Ha(t){return t._end=ja(t._start+(t._tDur/Math.abs(t._ts||t._rts||X)||0))}function Ia(t,e){var r=t._dp;return r&&r.smoothChildTiming&&t._ts&&(t._start=ja(r._time-(0X)&&e.render(r,!0)),Aa(t,e)._dp&&t._initted&&t._time>=t._dur&&t._ts){if(t._dur(n=Math.abs(n))&&(a=i,o=n);return a}function tb(t){return za(t),t.scrollTrigger&&t.scrollTrigger.kill(!!L),t.progress()<1&&Ct(t,"onInterrupt"),t}function wb(t){if(t)if(t=!t.name&&t.default||t,x()||t.headless){var e=t.name,r=s(t),i=e&&!r&&t.init?function(){this._props=[]}:t,n={init:T,render:he,add:Wt,kill:ce,modifier:fe,rawVars:0},a={targetTest:0,get:0,getSetter:ne,aliases:{},register:0};if(Ft(),t!==i){if(pt[e])return;qa(i,qa(ua(t,n),a)),yt(i.prototype,yt(n,ua(t,a))),pt[i.prop=e]=i,t.targetTest&&(gt.push(i),ft[e]=1),e=("css"===e?"CSS":e.charAt(0).toUpperCase()+e.substr(1))+"Plugin"}S(e,i),t.register&&t.register(ze,i,_e)}else At.push(t)}function zb(t,e,r){return(6*(t+=t<0?1:1>16,e>>8&St,e&St]:0:zt.black;if(!p){if(","===e.substr(-1)&&(e=e.substr(0,e.length-1)),zt[e])p=zt[e];else if("#"===e.charAt(0)){if(e.length<6&&(e="#"+(n=e.charAt(1))+n+(a=e.charAt(2))+a+(s=e.charAt(3))+s+(5===e.length?e.charAt(4)+e.charAt(4):"")),9===e.length)return[(p=parseInt(e.substr(1,6),16))>>16,p>>8&St,p&St,parseInt(e.substr(7),16)/255];p=[(e=parseInt(e.substr(1),16))>>16,e>>8&St,e&St]}else if("hsl"===e.substr(0,3))if(p=c=e.match(tt),r){if(~e.indexOf("="))return p=e.match(et),i&&p.length<4&&(p[3]=1),p}else o=+p[0]%360/360,u=p[1]/100,n=2*(h=p[2]/100)-(a=h<=.5?h*(u+1):h+u-h*u),3=U?u.endTime(!1):t._dur;return r(e)&&(isNaN(e)||e in o)?(a=e.charAt(0),s="%"===e.substr(-1),n=e.indexOf("="),"<"===a||">"===a?(0<=n&&(e=e.replace(/=/,"")),("<"===a?u._start:u.endTime(0<=u._repeat))+(parseFloat(e.substr(1))||0)*(s?(n<0?u:i).totalDuration()/100:1)):n<0?(e in o||(o[e]=h),o[e]):(a=parseFloat(e.charAt(n-1)+e.substr(n+1)),s&&i&&(a=a/100*(Z(i)?i[0]:i).totalDuration()),1=r&&te)return i;i=i._next}else for(i=t._last;i&&i._start>=r;){if("isPause"===i.data&&i._start=n._start)&&n._ts&&h!==n){if(n.parent!==this)return this.render(t,e,r);if(n.render(0=this.totalDuration()||!v&&_)&&(f!==this._start&&Math.abs(l)===Math.abs(this._ts)||this._lock||(!t&&g||!(v===m&&0=i&&(a instanceof $t?e&&n.push(a):(r&&n.push(a),t&&n.push.apply(n,a.getChildren(!0,e,r)))),a=a._next;return n},e.getById=function getById(t){for(var e=this.getChildren(1,1,1),r=e.length;r--;)if(e[r].vars.id===t)return e[r]},e.remove=function remove(t){return r(t)?this.removeLabel(t):s(t)?this.killTweensOf(t):(ya(this,t),t===this._recent&&(this._recent=this._last),Aa(this))},e.totalTime=function totalTime(t,e){return arguments.length?(this._forcing=1,!this._dp&&this._ts&&(this._start=ja(Rt.time-(0r:!r||s.isActive())&&n.push(s):(i=s.getTweensOf(a,r)).length&&n.push.apply(n,i),s=s._next;return n},e.tweenTo=function tweenTo(t,e){e=e||{};var r,i=this,n=xt(i,t),a=e.startAt,s=e.onStart,o=e.onStartParams,u=e.immediateRender,h=$t.to(i,qa({ease:e.ease||"none",lazy:!1,immediateRender:!1,time:n,overwrite:"auto",duration:e.duration||Math.abs((n-(a&&"time"in a?a.time:i._time))/i.timeScale())||X,onStart:function onStart(){if(i.pause(),!r){var t=e.duration||Math.abs((n-(a&&"time"in a?a.time:i._time))/i.timeScale());h._dur!==t&&Ra(h,t,0,1).render(h._time,!0,!0),r=1}s&&s.apply(h,o||[])}},e));return u?h.render(0):h},e.tweenFromTo=function tweenFromTo(t,e,r){return this.tweenTo(e,qa({startAt:{time:xt(this,t)}},r))},e.recent=function recent(){return this._recent},e.nextLabel=function nextLabel(t){return void 0===t&&(t=this._time),rb(this,xt(this,t))},e.previousLabel=function previousLabel(t){return void 0===t&&(t=this._time),rb(this,xt(this,t),1)},e.currentLabel=function currentLabel(t){return arguments.length?this.seek(t,!0):this.previousLabel(this._time+X)},e.shiftChildren=function shiftChildren(t,e,r){void 0===r&&(r=0);for(var i,n=this._first,a=this.labels;n;)n._start>=r&&(n._start+=t,n._end+=t),n=n._next;if(e)for(i in a)a[i]>=r&&(a[i]+=t);return Aa(this)},e.invalidate=function invalidate(t){var e=this._first;for(this._lock=0;e;)e.invalidate(t),e=e._next;return i.prototype.invalidate.call(this,t)},e.clear=function clear(t){void 0===t&&(t=!0);for(var e,r=this._first;r;)e=r._next,this.remove(r),r=e;return this._dp&&(this._time=this._tTime=this._pTime=0),t&&(this.labels={}),Aa(this)},e.totalDuration=function totalDuration(t){var e,r,i,n=0,a=this,s=a._last,o=U;if(arguments.length)return a.timeScale((a._repeat<0?a.duration():a.totalDuration())/(a.reversed()?-t:t));if(a._dirty){for(i=a.parent;s;)e=s._prev,s._dirty&&s.totalDuration(),o<(r=s._start)&&a._sort&&s._ts&&!a._lock?(a._lock=1,Ka(a,s,r-s._delay,1)._lock=0):o=r,r<0&&s._ts&&(n-=r,(!i&&!a._dp||i&&i.smoothChildTiming)&&(a._start+=r/a._ts,a._time-=r,a._tTime-=r),a.shiftChildren(-r,!1,-Infinity),o=0),s._end>n&&s._ts&&(n=s._end),s=e;Ra(a,a===I&&a._time>n?a._time:n,1,1),a._dirty=0}return a._tDur},Timeline.updateRoot=function updateRoot(t){if(I._ts&&(na(I,Ga(t,I)),f=Rt.frame),Rt.frame>=mt){mt+=q.autoSleep||120;var e=I._first;if((!e||!e._ts)&&q.autoSleep&&Rt._listeners.length<2){for(;e&&!e._ts;)e=e._next;e||Rt.sleep()}}},Timeline}(Ut);qa(Xt.prototype,{_lock:0,_hasPause:0,_forcing:0});function ac(t,e,i,n,a,o){var u,h,l,f;if(pt[t]&&!1!==(u=new pt[t]).init(a,u.rawVars?e[t]:function _processVars(t,e,i,n,a){if(s(t)&&(t=Kt(t,a,e,i,n)),!v(t)||t.style&&t.nodeType||Z(t)||$(t))return r(t)?Kt(t,a,e,i,n):t;var o,u={};for(o in t)u[o]=Kt(t[o],a,e,i,n);return u}(e[t],n,a,o,i),i,n,o)&&(i._pt=h=new _e(i._pt,a,t,0,1,u.render,u,0,u.priority),i!==d))for(l=i._ptLookup[i._targets.indexOf(a)],f=u._props.length;f--;)l[u._props[f]]=h;return u}function gc(t,r,e,i){var n,a,s=r.ease||i||"power1.inOut";if(Z(r))a=e[t]||(e[t]=[]),r.forEach(function(t,e){return a.push({t:e/(r.length-1)*100,v:t,e:s})});else for(n in r)a=e[n]||(e[n]=[]),"ease"===n||a.push({t:parseFloat(t),v:r[n],e:s})}var Nt,Gt,Wt=function _addPropTween(t,e,i,n,a,o,u,h,l,f){s(n)&&(n=n(a||0,t,o));var d,c=t[e],p="get"!==i?i:s(c)?l?t[e.indexOf("set")||!s(t["get"+e.substr(3)])?e:"get"+e.substr(3)](l):t[e]():c,_=s(c)?l?re:te:Zt;if(r(n)&&(~n.indexOf("random(")&&(n=ob(n)),"="===n.charAt(1)&&(!(d=ka(p,n)+(Ya(p)||0))&&0!==d||(n=d))),!f||p!==n||Gt)return isNaN(p*n)||""===n?(c||e in t||Q(e,n),function _addComplexStringPropTween(t,e,r,i,n,a,s){var o,u,h,l,f,d,c,p,_=new _e(this._pt,t,e,0,1,ue,null,n),m=0,g=0;for(_.b=r,_.e=i,r+="",(c=~(i+="").indexOf("random("))&&(i=ob(i)),a&&(a(p=[r,i],t,e),r=p[0],i=p[1]),u=r.match(it)||[];o=it.exec(i);)l=o[0],f=i.substring(m,o.index),h?h=(h+1)%5:"rgba("===f.substr(-5)&&(h=1),l!==u[g++]&&(d=parseFloat(u[g-1])||0,_._pt={_next:_._pt,p:f||1===g?f:",",s:d,c:"="===l.charAt(1)?ka(d,l)-d:parseFloat(l)-d,m:h&&h<4?Math.round:0},m=it.lastIndex);return _.c=m")}),s.duration();else{for(l in u={},x)"ease"===l||"easeEach"===l||gc(l,x[l],u,x.easeEach);for(l in u)for(A=u[l].sort(function(t,e){return t.t-e.t}),o=E=0;o=t._tDur||e<0)&&t.ratio===u&&(u&&za(t,1),r||L||(Ct(t,u?"onComplete":"onReverseComplete",!0),t._prom&&t._prom()))}else t._zTime||(t._zTime=e)}(this,t,e,r);return this},e.targets=function targets(){return this._targets},e.invalidate=function invalidate(t){return t&&this.vars.runBackwards||(this._startAt=0),this._pt=this._op=this._onUpdate=this._lazy=this.ratio=0,this._ptLookup=[],this.timeline&&this.timeline.invalidate(t),D.prototype.invalidate.call(this,t)},e.resetTo=function resetTo(t,e,r,i,n){c||Rt.wake(),this._ts||this.play();var a,s=Math.min(this._dur,(this._dp._time-this._start)*this._ts);return this._initted||Qt(this,s),a=this._ease(s/this._dur),function _updatePropTweens(t,e,r,i,n,a,s,o){var u,h,l,f,d=(t._pt&&t._ptCache||(t._ptCache={}))[e];if(!d)for(d=t._ptCache[e]=[],l=t._ptLookup,f=t._targets.length;f--;){if((u=l[f][e])&&u.d&&u.d._pt)for(u=u.d._pt;u&&u.p!==e&&u.fp!==e;)u=u._next;if(!u)return Gt=1,t.vars[e]="+=0",Qt(t,s),Gt=0,o?R(e+" not eligible for reset"):1;d.push(u)}for(f=d.length;f--;)(u=(h=d[f])._pt||h).s=!i&&0!==i||n?u.s+(i||0)+a*u.c:i,u.c=r-u.s,h.e&&(h.e=ia(r)+Ya(h.e)),h.b&&(h.b=u.s+Ya(h.b))}(this,t,e,r,i,a,s,n)?this.resetTo(t,e,r,i,1):(Ia(this,0),this.parent||xa(this._dp,this,"_first","_last",this._dp._sort?"_start":0),this.render(0))},e.kill=function kill(t,e){if(void 0===e&&(e="all"),!(t||e&&"all"!==e))return this._lazy=this._pt=0,this.parent?tb(this):this;if(this.timeline){var i=this.timeline.totalDuration();return this.timeline.killTweensOf(t,e,Nt&&!0!==Nt.vars.overwrite)._first||tb(this),this.parent&&i!==this.timeline.totalDuration()&&Ra(this,this._dur*this.timeline._tDur/i,0,1),this}var n,a,s,o,u,h,l,f=this._targets,d=t?Mt(t):f,c=this._ptLookup,p=this._pt;if((!e||"all"===e)&&function _arraysMatch(t,e){for(var r=t.length,i=r===e.length;i&&r--&&t[r]===e[r];);return r<0}(f,d))return"all"===e&&(this._pt=0),tb(this);for(n=this._op=this._op||[],"all"!==e&&(r(e)&&(u={},ha(e,function(t){return u[t]=1}),e=u),e=function _addAliasesToVars(t,e){var r,i,n,a,s=t[0]?fa(t[0]).harness:0,o=s&&s.aliases;if(!o)return e;for(i in r=yt({},e),o)if(i in r)for(n=(a=o[i].split(",")).length;n--;)r[a[n]]=r[i];return r}(f,e)),l=f.length;l--;)if(~d.indexOf(f[l]))for(u in a=c[l],"all"===e?(n[l]=e,o=a,s={}):(s=n[l]=n[l]||{},o=e),o)(h=a&&a[u])&&("kill"in h.d&&!0!==h.d.kill(u)||ya(this,h,"_pt"),delete a[u]),"all"!==s&&(s[u]=1);return this._initted&&!this._pt&&p&&tb(this),this},Tween.to=function to(t,e,r){return new Tween(t,e,r)},Tween.from=function from(t,e){return Va(1,arguments)},Tween.delayedCall=function delayedCall(t,e,r,i){return new Tween(e,0,{immediateRender:!1,lazy:!1,overwrite:!1,delay:t,onComplete:e,onReverseComplete:e,onCompleteParams:r,onReverseCompleteParams:r,callbackScope:i})},Tween.fromTo=function fromTo(t,e,r){return Va(2,arguments)},Tween.set=function set(t,e){return e.duration=0,e.repeatDelay||(e.repeat=0),new Tween(t,e)},Tween.killTweensOf=function killTweensOf(t,e,r){return I.killTweensOf(t,e,r)},Tween}(Ut);qa($t.prototype,{_targets:[],_lazy:0,_startAt:0,_op:0,_onInit:0}),ha("staggerTo,staggerFrom,staggerFromTo",function(r){$t[r]=function(){var t=new Xt,e=kt.call(arguments,0);return e.splice("staggerFromTo"===r?5:4,0,0),t[r].apply(t,e)}});function oc(t,e,r){return t.setAttribute(e,r)}function wc(t,e,r,i){i.mSet(t,e,i.m.call(i.tween,r,i.mt),i)}var Zt=function _setterPlain(t,e,r){return t[e]=r},te=function _setterFunc(t,e,r){return t[e](r)},re=function _setterFuncWithParam(t,e,r,i){return t[e](i.fp,r)},ne=function _getSetter(t,e){return s(t[e])?te:u(t[e])&&t.setAttribute?oc:Zt},ae=function _renderPlain(t,e){return e.set(e.t,e.p,Math.round(1e6*(e.s+e.c*t))/1e6,e)},se=function _renderBoolean(t,e){return e.set(e.t,e.p,!!(e.s+e.c*t),e)},ue=function _renderComplexString(t,e){var r=e._pt,i="";if(!t&&e.b)i=e.b;else if(1===t&&e.e)i=e.e;else{for(;r;)i=r.p+(r.m?r.m(r.s+r.c*t):Math.round(1e4*(r.s+r.c*t))/1e4)+i,r=r._next;i+=e.c}e.set(e.t,e.p,i,e)},he=function _renderPropTweens(t,e){for(var r=e._pt;r;)r.r(t,r.d),r=r._next},fe=function _addPluginModifier(t,e,r,i){for(var n,a=this._pt;a;)n=a._next,a.p===i&&a.modifier(t,e,r),a=n},ce=function _killPropTweensOf(t){for(var e,r,i=this._pt;i;)r=i._next,i.p===t&&!i.op||i.op===t?ya(this,i,"_pt"):i.dep||(e=1),i=r;return!e},pe=function _sortPropTweensByPriority(t){for(var e,r,i,n,a=t._pt;a;){for(e=a._next,r=i;r&&r.pr>a.pr;)r=r._next;(a._prev=r?r._prev:n)?a._prev._next=a:i=a,(a._next=r)?r._prev=a:n=a,a=e}t._pt=i},_e=(PropTween.prototype.modifier=function modifier(t,e,r){this.mSet=this.mSet||this.set,this.set=wc,this.m=t,this.mt=r,this.tween=e},PropTween);function PropTween(t,e,r,i,n,a,s,o,u){this.t=e,this.s=i,this.c=n,this.p=r,this.r=a||ae,this.d=s||this,this.set=o||Zt,this.pr=u||0,(this._next=t)&&(t._prev=this)}ha(vt+"parent,duration,ease,delay,overwrite,runBackwards,startAt,yoyo,immediateRender,repeat,repeatDelay,data,paused,reversed,lazy,callbackScope,stringFilter,id,yoyoEase,stagger,inherit,repeatRefresh,keyframes,autoRevert,scrollTrigger",function(t){return ft[t]=1}),ot.TweenMax=ot.TweenLite=$t,ot.TimelineLite=ot.TimelineMax=Xt,I=new Xt({sortChildren:!1,defaults:V,autoRemoveChildren:!0,id:"root",smoothChildTiming:!0}),q.stringFilter=Fb;function Ec(t){return(ye[t]||Te).map(function(t){return t()})}function Fc(){var t=Date.now(),o=[];2{setTimeout((()=>{this.progress(t,e,i)}))};this.images.forEach((function(e){e.once("progress",t),e.check()}))},n.prototype.progress=function(t,e,i){this.progressedCount++,this.hasAnyBroken=this.hasAnyBroken||!t.isLoaded,this.emitEvent("progress",[this,t,e]),this.jqDeferred&&this.jqDeferred.notify&&this.jqDeferred.notify(this,t),this.progressedCount===this.images.length&&this.complete(),this.options.debug&&s&&s.log(`progress: ${i}`,t,e)},n.prototype.complete=function(){let t=this.hasAnyBroken?"fail":"done";if(this.isComplete=!0,this.emitEvent(t,[this]),this.emitEvent("always",[this]),this.jqDeferred){let t=this.hasAnyBroken?"reject":"resolve";this.jqDeferred[t](this)}},h.prototype=Object.create(e.prototype),h.prototype.check=function(){this.getIsImageComplete()?this.confirm(0!==this.img.naturalWidth,"naturalWidth"):(this.proxyImage=new Image,this.img.crossOrigin&&(this.proxyImage.crossOrigin=this.img.crossOrigin),this.proxyImage.addEventListener("load",this),this.proxyImage.addEventListener("error",this),this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.proxyImage.src=this.img.currentSrc||this.img.src)},h.prototype.getIsImageComplete=function(){return this.img.complete&&this.img.naturalWidth},h.prototype.confirm=function(t,e){this.isLoaded=t;let{parentNode:i}=this.img,s="PICTURE"===i.nodeName?i:this.img;this.emitEvent("progress",[this,s,e])},h.prototype.handleEvent=function(t){let e="on"+t.type;this[e]&&this[e](t)},h.prototype.onload=function(){this.confirm(!0,"onload"),this.unbindEvents()},h.prototype.onerror=function(){this.confirm(!1,"onerror"),this.unbindEvents()},h.prototype.unbindEvents=function(){this.proxyImage.removeEventListener("load",this),this.proxyImage.removeEventListener("error",this),this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype=Object.create(h.prototype),d.prototype.check=function(){this.img.addEventListener("load",this),this.img.addEventListener("error",this),this.img.src=this.url,this.getIsImageComplete()&&(this.confirm(0!==this.img.naturalWidth,"naturalWidth"),this.unbindEvents())},d.prototype.unbindEvents=function(){this.img.removeEventListener("load",this),this.img.removeEventListener("error",this)},d.prototype.confirm=function(t,e){this.isLoaded=t,this.emitEvent("progress",[this,this.element,e])},n.makeJQueryPlugin=function(e){(e=e||t.jQuery)&&(i=e,i.fn.imagesLoaded=function(t,e){return new n(this,t,e).jqDeferred.promise(i(this))})},n.makeJQueryPlugin(),n}));
--------------------------------------------------------------------------------
/js/lenis.min.js:
--------------------------------------------------------------------------------
1 | !function(t,i){"object"==typeof exports&&"undefined"!=typeof module?module.exports=i():"function"==typeof define&&define.amd?define(i):(t="undefined"!=typeof globalThis?globalThis:t||self).Lenis=i()}(this,(function(){"use strict";function clamp(t,i,e){return Math.max(t,Math.min(i,e))}class Animate{constructor(){this.isRunning=!1,this.value=0,this.from=0,this.to=0,this.duration=0,this.currentTime=0}advance(t){var i;if(!this.isRunning)return;let e=!1;if(this.duration&&this.easing){this.currentTime+=t;const i=clamp(0,this.currentTime/this.duration,1);e=i>=1;const s=e?1:this.easing(i);this.value=this.from+(this.to-this.from)*s}else this.lerp?(this.value=function damp(t,i,e,s){return function lerp(t,i,e){return(1-e)*t+e*i}(t,i,1-Math.exp(-e*s))}(this.value,this.to,60*this.lerp,t),Math.round(this.value)===this.to&&(this.value=this.to,e=!0)):(this.value=this.to,e=!0);e&&this.stop(),null===(i=this.onUpdate)||void 0===i||i.call(this,this.value,e)}stop(){this.isRunning=!1}fromTo(t,i,{lerp:e,duration:s,easing:o,onStart:n,onUpdate:l}){this.from=this.value=t,this.to=i,this.lerp=e,this.duration=s,this.easing=o,this.currentTime=0,this.isRunning=!0,null==n||n(),this.onUpdate=l}}class Dimensions{constructor({wrapper:t,content:i,autoResize:e=!0,debounce:s=250}={}){this.width=0,this.height=0,this.scrollWidth=0,this.scrollHeight=0,this.resize=()=>{this.onWrapperResize(),this.onContentResize()},this.onWrapperResize=()=>{this.wrapper===window?(this.width=window.innerWidth,this.height=window.innerHeight):this.wrapper instanceof HTMLElement&&(this.width=this.wrapper.clientWidth,this.height=this.wrapper.clientHeight)},this.onContentResize=()=>{this.wrapper===window?(this.scrollHeight=this.content.scrollHeight,this.scrollWidth=this.content.scrollWidth):this.wrapper instanceof HTMLElement&&(this.scrollHeight=this.wrapper.scrollHeight,this.scrollWidth=this.wrapper.scrollWidth)},this.wrapper=t,this.content=i,e&&(this.debouncedResize=function debounce(t,i){let e;return function(){let s=arguments,o=this;clearTimeout(e),e=setTimeout((function(){t.apply(o,s)}),i)}}(this.resize,s),this.wrapper===window?window.addEventListener("resize",this.debouncedResize,!1):(this.wrapperResizeObserver=new ResizeObserver(this.debouncedResize),this.wrapperResizeObserver.observe(this.wrapper)),this.contentResizeObserver=new ResizeObserver(this.debouncedResize),this.contentResizeObserver.observe(this.content)),this.resize()}destroy(){var t,i;null===(t=this.wrapperResizeObserver)||void 0===t||t.disconnect(),null===(i=this.contentResizeObserver)||void 0===i||i.disconnect(),window.removeEventListener("resize",this.debouncedResize,!1)}get limit(){return{x:this.scrollWidth-this.width,y:this.scrollHeight-this.height}}}class Emitter{constructor(){this.events={}}emit(t,...i){let e=this.events[t]||[];for(let t=0,s=e.length;t{var e;this.events[t]=null===(e=this.events[t])||void 0===e?void 0:e.filter((t=>i!==t))}}off(t,i){var e;this.events[t]=null===(e=this.events[t])||void 0===e?void 0:e.filter((t=>i!==t))}destroy(){this.events={}}}const t=100/6;class VirtualScroll{constructor(i,{wheelMultiplier:e=1,touchMultiplier:s=1}){this.lastDelta={x:0,y:0},this.windowWidth=0,this.windowHeight=0,this.onTouchStart=t=>{const{clientX:i,clientY:e}=t.targetTouches?t.targetTouches[0]:t;this.touchStart.x=i,this.touchStart.y=e,this.lastDelta={x:0,y:0},this.emitter.emit("scroll",{deltaX:0,deltaY:0,event:t})},this.onTouchMove=t=>{var i,e,s,o;const{clientX:n,clientY:l}=t.targetTouches?t.targetTouches[0]:t,r=-(n-(null!==(e=null===(i=this.touchStart)||void 0===i?void 0:i.x)&&void 0!==e?e:0))*this.touchMultiplier,h=-(l-(null!==(o=null===(s=this.touchStart)||void 0===s?void 0:s.y)&&void 0!==o?o:0))*this.touchMultiplier;this.touchStart.x=n,this.touchStart.y=l,this.lastDelta={x:r,y:h},this.emitter.emit("scroll",{deltaX:r,deltaY:h,event:t})},this.onTouchEnd=t=>{this.emitter.emit("scroll",{deltaX:this.lastDelta.x,deltaY:this.lastDelta.y,event:t})},this.onWheel=i=>{let{deltaX:e,deltaY:s,deltaMode:o}=i;e*=1===o?t:2===o?this.windowWidth:1,s*=1===o?t:2===o?this.windowHeight:1,e*=this.wheelMultiplier,s*=this.wheelMultiplier,this.emitter.emit("scroll",{deltaX:e,deltaY:s,event:i})},this.onWindowResize=()=>{this.windowWidth=window.innerWidth,this.windowHeight=window.innerHeight},this.element=i,this.wheelMultiplier=e,this.touchMultiplier=s,this.touchStart={x:null,y:null},this.emitter=new Emitter,window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize(),this.element.addEventListener("wheel",this.onWheel,{passive:!1}),this.element.addEventListener("touchstart",this.onTouchStart,{passive:!1}),this.element.addEventListener("touchmove",this.onTouchMove,{passive:!1}),this.element.addEventListener("touchend",this.onTouchEnd,{passive:!1})}on(t,i){return this.emitter.on(t,i)}destroy(){this.emitter.destroy(),window.removeEventListener("resize",this.onWindowResize,!1),this.element.removeEventListener("wheel",this.onWheel),this.element.removeEventListener("touchstart",this.onTouchStart),this.element.removeEventListener("touchmove",this.onTouchMove),this.element.removeEventListener("touchend",this.onTouchEnd)}}return class Lenis{constructor({wrapper:t=window,content:i=document.documentElement,wheelEventsTarget:e=t,eventsTarget:s=e,smoothWheel:o=!0,syncTouch:n=!1,syncTouchLerp:l=.075,touchInertiaMultiplier:r=35,duration:h,easing:a=(t=>Math.min(1,1.001-Math.pow(2,-10*t))),lerp:c=.1,infinite:d=!1,orientation:u="vertical",gestureOrientation:p="vertical",touchMultiplier:m=1,wheelMultiplier:v=1,autoResize:g=!0,prevent:w,virtualScroll:S,__experimental__naiveDimensions:f=!1}={}){this.__isScrolling=!1,this.__isStopped=!1,this.__isLocked=!1,this.userData={},this.lastVelocity=0,this.velocity=0,this.direction=0,this.onPointerDown=t=>{1===t.button&&this.reset()},this.onVirtualScroll=t=>{if("function"==typeof this.options.virtualScroll&&!1===this.options.virtualScroll(t))return;const{deltaX:i,deltaY:e,event:s}=t;if(this.emitter.emit("virtual-scroll",{deltaX:i,deltaY:e,event:s}),s.ctrlKey)return;const o=s.type.includes("touch"),n=s.type.includes("wheel");this.isTouching="touchstart"===s.type||"touchmove"===s.type;if(this.options.syncTouch&&o&&"touchstart"===s.type&&!this.isStopped&&!this.isLocked)return void this.reset();const l=0===i&&0===e,r="vertical"===this.options.gestureOrientation&&0===e||"horizontal"===this.options.gestureOrientation&&0===i;if(l||r)return;let h=s.composedPath();h=h.slice(0,h.indexOf(this.rootElement));const a=this.options.prevent;if(h.find((t=>{var i,e,s,l,r;return t instanceof Element&&("function"==typeof a&&(null==a?void 0:a(t))||(null===(i=t.hasAttribute)||void 0===i?void 0:i.call(t,"data-lenis-prevent"))||o&&(null===(e=t.hasAttribute)||void 0===e?void 0:e.call(t,"data-lenis-prevent-touch"))||n&&(null===(s=t.hasAttribute)||void 0===s?void 0:s.call(t,"data-lenis-prevent-wheel"))||(null===(l=t.classList)||void 0===l?void 0:l.contains("lenis"))&&!(null===(r=t.classList)||void 0===r?void 0:r.contains("lenis-stopped")))})))return;if(this.isStopped||this.isLocked)return void s.preventDefault();if(!(this.options.syncTouch&&o||this.options.smoothWheel&&n))return this.isScrolling="native",void this.animate.stop();s.preventDefault();let c=e;"both"===this.options.gestureOrientation?c=Math.abs(e)>Math.abs(i)?e:i:"horizontal"===this.options.gestureOrientation&&(c=i);const d=o&&this.options.syncTouch,u=o&&"touchend"===s.type&&Math.abs(c)>5;u&&(c=this.velocity*this.options.touchInertiaMultiplier),this.scrollTo(this.targetScroll+c,Object.assign({programmatic:!1},d?{lerp:u?this.options.syncTouchLerp:1}:{lerp:this.options.lerp,duration:this.options.duration,easing:this.options.easing}))},this.onNativeScroll=()=>{if(clearTimeout(this.__resetVelocityTimeout),delete this.__resetVelocityTimeout,this.__preventNextNativeScrollEvent)delete this.__preventNextNativeScrollEvent;else if(!1===this.isScrolling||"native"===this.isScrolling){const t=this.animatedScroll;this.animatedScroll=this.targetScroll=this.actualScroll,this.lastVelocity=this.velocity,this.velocity=this.animatedScroll-t,this.direction=Math.sign(this.animatedScroll-t),this.isScrolling="native",this.emit(),0!==this.velocity&&(this.__resetVelocityTimeout=setTimeout((()=>{this.lastVelocity=this.velocity,this.velocity=0,this.isScrolling=!1,this.emit()}),400))}},window.lenisVersion="1.1.9",t&&t!==document.documentElement&&t!==document.body||(t=window),this.options={wrapper:t,content:i,wheelEventsTarget:e,eventsTarget:s,smoothWheel:o,syncTouch:n,syncTouchLerp:l,touchInertiaMultiplier:r,duration:h,easing:a,lerp:c,infinite:d,gestureOrientation:p,orientation:u,touchMultiplier:m,wheelMultiplier:v,autoResize:g,prevent:w,virtualScroll:S,__experimental__naiveDimensions:f},this.animate=new Animate,this.emitter=new Emitter,this.dimensions=new Dimensions({wrapper:t,content:i,autoResize:g}),this.updateClassName(),this.userData={},this.time=0,this.velocity=this.lastVelocity=0,this.isLocked=!1,this.isStopped=!1,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.options.wrapper.addEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.addEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll=new VirtualScroll(s,{touchMultiplier:m,wheelMultiplier:v}),this.virtualScroll.on("scroll",this.onVirtualScroll)}destroy(){this.emitter.destroy(),this.options.wrapper.removeEventListener("scroll",this.onNativeScroll,!1),this.options.wrapper.removeEventListener("pointerdown",this.onPointerDown,!1),this.virtualScroll.destroy(),this.dimensions.destroy(),this.cleanUpClassName()}on(t,i){return this.emitter.on(t,i)}off(t,i){return this.emitter.off(t,i)}setScroll(t){this.isHorizontal?this.rootElement.scrollLeft=t:this.rootElement.scrollTop=t}resize(){this.dimensions.resize()}emit(){this.emitter.emit("scroll",this)}reset(){this.isLocked=!1,this.isScrolling=!1,this.animatedScroll=this.targetScroll=this.actualScroll,this.lastVelocity=this.velocity=0,this.animate.stop()}start(){this.isStopped&&(this.isStopped=!1,this.reset())}stop(){this.isStopped||(this.isStopped=!0,this.animate.stop(),this.reset())}raf(t){const i=t-(this.time||t);this.time=t,this.animate.advance(.001*i)}scrollTo(t,{offset:i=0,immediate:e=!1,lock:s=!1,duration:o=this.options.duration,easing:n=this.options.easing,lerp:l=this.options.lerp,onStart:r,onComplete:h,force:a=!1,programmatic:c=!0,userData:d={}}={}){if(!this.isStopped&&!this.isLocked||a){if("string"==typeof t&&["top","left","start"].includes(t))t=0;else if("string"==typeof t&&["bottom","right","end"].includes(t))t=this.limit;else{let e;if("string"==typeof t?e=document.querySelector(t):t instanceof HTMLElement&&(null==t?void 0:t.nodeType)&&(e=t),e){if(this.options.wrapper!==window){const t=this.rootElement.getBoundingClientRect();i-=this.isHorizontal?t.left:t.top}const s=e.getBoundingClientRect();t=(this.isHorizontal?s.left:s.top)+this.animatedScroll}}if("number"==typeof t&&(t+=i,t=Math.round(t),this.options.infinite?c&&(this.targetScroll=this.animatedScroll=this.scroll):t=clamp(0,t,this.limit),t!==this.targetScroll)){if(this.userData=d,e)return this.animatedScroll=this.targetScroll=t,this.setScroll(this.scroll),this.reset(),this.preventNextNativeScrollEvent(),this.emit(),null==h||h(this),void(this.userData={});c||(this.targetScroll=t),this.animate.fromTo(this.animatedScroll,t,{duration:o,easing:n,lerp:l,onStart:()=>{s&&(this.isLocked=!0),this.isScrolling="smooth",null==r||r(this)},onUpdate:(t,i)=>{this.isScrolling="smooth",this.lastVelocity=this.velocity,this.velocity=t-this.animatedScroll,this.direction=Math.sign(this.velocity),this.animatedScroll=t,this.setScroll(this.scroll),c&&(this.targetScroll=t),i||this.emit(),i&&(this.reset(),this.emit(),null==h||h(this),this.userData={},this.preventNextNativeScrollEvent())}})}}}preventNextNativeScrollEvent(){this.__preventNextNativeScrollEvent=!0,requestAnimationFrame((()=>{delete this.__preventNextNativeScrollEvent}))}get rootElement(){return this.options.wrapper===window?document.documentElement:this.options.wrapper}get limit(){return this.options.__experimental__naiveDimensions?this.isHorizontal?this.rootElement.scrollWidth-this.rootElement.clientWidth:this.rootElement.scrollHeight-this.rootElement.clientHeight:this.dimensions.limit[this.isHorizontal?"x":"y"]}get isHorizontal(){return"horizontal"===this.options.orientation}get actualScroll(){return this.isHorizontal?this.rootElement.scrollLeft:this.rootElement.scrollTop}get scroll(){return this.options.infinite?function modulo(t,i){return(t%i+i)%i}(this.animatedScroll,this.limit):this.animatedScroll}get progress(){return 0===this.limit?1:this.scroll/this.limit}get isScrolling(){return this.__isScrolling}set isScrolling(t){this.__isScrolling!==t&&(this.__isScrolling=t,this.updateClassName())}get isStopped(){return this.__isStopped}set isStopped(t){this.__isStopped!==t&&(this.__isStopped=t,this.updateClassName())}get isLocked(){return this.__isLocked}set isLocked(t){this.__isLocked!==t&&(this.__isLocked=t,this.updateClassName())}get isSmooth(){return"smooth"===this.isScrolling}get className(){let t="lenis";return this.isStopped&&(t+=" lenis-stopped"),this.isLocked&&(t+=" lenis-locked"),this.isScrolling&&(t+=" lenis-scrolling"),"smooth"===this.isScrolling&&(t+=" lenis-smooth"),t}updateClassName(){this.cleanUpClassName(),this.rootElement.className=`${this.rootElement.className} ${this.className}`.trim()}cleanUpClassName(){this.rootElement.className=this.rootElement.className.replace(/lenis(-\w+)?/g,"").trim()}}}));
2 | //# sourceMappingURL=lenis.min.js.map
--------------------------------------------------------------------------------
/js/main.js:
--------------------------------------------------------------------------------
1 | import { preloadImages } from './utils.js';
2 |
3 | // Select all elements that have the data-filter attribute
4 | const elements = [...document.querySelectorAll('[data-filter]')];
5 |
6 | // A Set to keep track of the scripts that have already been imported
7 | const importedScripts = new Set();
8 |
9 | // Function to initialize animations and scripts
10 | const init = async () => {
11 | // Select all elements with the class .deco__item
12 | const decoItems = document.querySelectorAll('.deco__item');
13 |
14 | // Loop through all .deco__item elements
15 | decoItems.forEach((item) => {
16 | // Generate a random translation value for the y-axis
17 | const randomY = Math.random() * 100 - 50; // Random value between -50% and 50%
18 |
19 | // Apply ScrollTrigger animation to translate the element on the y-axis
20 | gsap.to(item, {
21 | yPercent: randomY, // Apply the random y-axis translation
22 | scrollTrigger: {
23 | trigger: item, // Trigger animation when the item enters the viewport
24 | start: 'top bottom', // Start the animation when the top of the item reaches the bottom of the viewport
25 | end: 'bottom top', // End the animation when the bottom of the item reaches the top of the viewport
26 | scrub: true, // Smoothly scrub the animation with the scroll
27 | },
28 | });
29 | });
30 |
31 | // Loop through all elements with the data-filter attribute
32 | for (const element of elements) {
33 | // Get the script name from the data-script attribute
34 | const scriptName = element.getAttribute('data-script');
35 |
36 | if (scriptName) {
37 | // Check if the script has already been imported
38 | if (!importedScripts.has(scriptName)) {
39 | try {
40 | // Dynamically import the script and mark it as imported
41 | const module = await import(`./${scriptName}.js`);
42 | importedScripts.add(scriptName);
43 | // Initialize the specific animation for this element
44 | module.default(element);
45 | } catch (error) {
46 | console.error(`Failed to load script: ${scriptName}.js`, error);
47 | }
48 | } else {
49 | // If the script is already imported, just initialize the animation
50 | const module = await import(`./${scriptName}.js`);
51 | module.default(element);
52 | }
53 | }
54 | }
55 | };
56 |
57 | // Call the init function to start the animations
58 | init();
59 |
60 | // Preloading images and initializing setup when complete
61 | preloadImages('.deco__item').then(() => document.body.classList.remove('loading')); // Remove the loading class from the body
62 |
--------------------------------------------------------------------------------
/js/smoothscroll.js:
--------------------------------------------------------------------------------
1 | // Initializes smooth scrolling with Lenis and integrates it with GSAP's ScrollTrigger.
2 | // Function to set up smooth scrolling.
3 | const initSmoothScrolling = () => {
4 | // Initialize Lenis for smooth scroll effects. Lerp value controls the smoothness.
5 | const lenis = new Lenis({ lerp: 0.2 });
6 |
7 | // Sync ScrollTrigger with Lenis' scroll updates.
8 | lenis.on('scroll', ScrollTrigger.update);
9 |
10 | // Ensure GSAP animations are in sync with Lenis' scroll frame updates.
11 | gsap.ticker.add(time => {
12 | lenis.raf(time * 1000); // Convert GSAP's time to milliseconds for Lenis.
13 | });
14 |
15 | // Turn off GSAP's default lag smoothing to avoid conflicts with Lenis.
16 | gsap.ticker.lagSmoothing(0);
17 | };
18 |
19 | // Activate the smooth scrolling feature.
20 | initSmoothScrolling();
21 |
--------------------------------------------------------------------------------
/js/utils.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Preloads images specified by the CSS selector.
3 | * @function
4 | * @param {string} [selector='img'] - CSS selector for target images.
5 | * @returns {Promise} - Resolves when all specified images are loaded.
6 | */
7 | const preloadImages = (selector = 'img') => {
8 | return new Promise((resolve) => {
9 | // The imagesLoaded library is used to ensure all images (including backgrounds) are fully loaded.
10 | imagesLoaded(document.querySelectorAll(selector), {background: true}, resolve);
11 | });
12 | };
13 |
14 | // Exporting utility functions for use in other modules.
15 | export {
16 | preloadImages
17 | };
--------------------------------------------------------------------------------