├── .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 | ![Image Title](https://tympanus.net/codrops/wp-content/uploads/2024/08/svgfilter_text.jpg) 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 |
87 |

#Scroll-based SVG #Filter Animations On #Text

88 | 93 |
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 | }; --------------------------------------------------------------------------------