├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── css └── base.css ├── favicon.ico ├── img ├── 1.jpg ├── 10.jpg ├── 11.jpg ├── 12.jpg ├── 13.jpg ├── 14.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg ├── 6.jpg ├── 7.jpg ├── 8.jpg └── 9.jpg ├── index.html ├── index2.html ├── index3.html └── js ├── Flip.min.js ├── demo1 └── index.js ├── demo2 └── index.js ├── demo3 └── index.js ├── gsap.min.js ├── imagesloaded.pkgd.min.js └── utils.js /.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 - 2022 [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 | # Grid to Slideshow Switch Animations 2 | 3 | Some ideas for grid to slideshow switch animations using GSAP's Flip plugin. 4 | 5 | ![Grid to Slider](https://tympanus.net/codrops/wp-content/uploads/2023/05/gridtoslider_feat.jpg) 6 | 7 | [Article on Codrops](https://tympanus.net/codrops/?p=71899) 8 | 9 | [Demo](http://tympanus.net/Development/GridToSlider/) 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: [Twitter](http://www.twitter.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: 14px; 9 | --color-text: hsl(300deg 33% 99%); 10 | --color-bg: hsl(120deg 3% 8%); 11 | --color-link: hsl(157deg 53% 61%); 12 | --color-link-hover: hsl(300deg 33% 99%); 13 | --title-gr-1: hsl(240deg 33% 99%); 14 | --title-gr-2: hsl(263deg 38% 53%); 15 | --color-desc: #999; 16 | } 17 | 18 | html, body { 19 | height: 100%; 20 | overflow: hidden; 21 | } 22 | 23 | body { 24 | margin: 0; 25 | color: var(--color-text); 26 | background-color: var(--color-bg); 27 | font-family: "vinila", -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif; 28 | -webkit-font-smoothing: antialiased; 29 | -moz-osx-font-smoothing: grayscale; 30 | text-transform: uppercase; 31 | } 32 | 33 | .demo-2 { 34 | --title-gr-2: hsl(177deg 68% 51%); 35 | } 36 | 37 | .demo-3 { 38 | --title-gr-2: hsl(334deg 54% 44%); 39 | } 40 | 41 | /* Page Loader */ 42 | .js .loading::before, 43 | .js .loading::after { 44 | content: ''; 45 | position: fixed; 46 | z-index: 1000; 47 | } 48 | 49 | .js .loading::before { 50 | top: 0; 51 | left: 0; 52 | width: 100%; 53 | height: 100%; 54 | background: var(--color-bg); 55 | } 56 | 57 | .js .loading::after { 58 | top: 50%; 59 | left: 50%; 60 | width: 60px; 61 | height: 60px; 62 | margin: -30px 0 0 -30px; 63 | border-radius: 50%; 64 | opacity: 0.4; 65 | background: var(--color-link); 66 | animation: loaderAnim 0.7s linear infinite alternate forwards; 67 | 68 | } 69 | 70 | @keyframes loaderAnim { 71 | to { 72 | opacity: 1; 73 | transform: scale3d(0.5,0.5,1); 74 | } 75 | } 76 | 77 | a { 78 | text-decoration: none; 79 | color: var(--color-link); 80 | outline: none; 81 | cursor: pointer; 82 | } 83 | 84 | a:hover { 85 | color: var(--color-link-hover); 86 | outline: none; 87 | } 88 | 89 | /* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */ 90 | a:focus { 91 | /* Provide a fallback style for browsers 92 | that don't support :focus-visible */ 93 | outline: none; 94 | background: lightgrey; 95 | } 96 | 97 | a:focus:not(:focus-visible) { 98 | /* Remove the focus indicator on mouse-focus for browsers 99 | that do support :focus-visible */ 100 | background: transparent; 101 | } 102 | 103 | a:focus-visible { 104 | /* Draw a very noticeable focus style for 105 | keyboard-focus on browsers that do support 106 | :focus-visible */ 107 | outline: 2px solid red; 108 | background: transparent; 109 | } 110 | 111 | .unbutton { 112 | background: none; 113 | border: 0; 114 | padding: 0; 115 | margin: 0; 116 | font: inherit; 117 | cursor: pointer; 118 | } 119 | 120 | .unbutton:focus { 121 | outline: none; 122 | } 123 | 124 | main { 125 | position: relative; 126 | display: grid; 127 | grid-template-areas: 'main'; 128 | width: 100%; 129 | height: 100vh; 130 | } 131 | 132 | .oh { 133 | position: relative; 134 | overflow: hidden; 135 | } 136 | 137 | .oh__inner { 138 | will-change: transform; 139 | display: inline-block; 140 | } 141 | 142 | .frame { 143 | grid-area: main; 144 | z-index: 1000; 145 | position: relative; 146 | width: 100%; 147 | padding: 1.5rem; 148 | display: grid; 149 | grid-template-columns: 100%; 150 | grid-template-areas: 'title' 'prev' 'sponsor' 'demos'; 151 | grid-gap: 0.5rem; 152 | justify-items: start; 153 | align-self: end; 154 | justify-self: start; 155 | pointer-events: none; 156 | align-items: center; 157 | 158 | } 159 | 160 | body #cdawrap { 161 | justify-self: start; 162 | } 163 | 164 | .frame a { 165 | pointer-events: auto; 166 | } 167 | 168 | .frame__title { 169 | grid-area: title; 170 | display: flex; 171 | } 172 | 173 | .frame__title-main { 174 | font-size: inherit; 175 | margin: 0; 176 | font-weight: inherit; 177 | } 178 | 179 | .frame__title-back { 180 | position: relative; 181 | display: flex; 182 | align-items: flex-end; 183 | margin-bottom: 0.15rem; 184 | } 185 | 186 | .frame__title-back span { 187 | display: none; 188 | } 189 | 190 | .frame__title-back svg { 191 | fill: currentColor; 192 | } 193 | 194 | .frame__prev { 195 | grid-area: prev; 196 | } 197 | 198 | .frame__demos { 199 | grid-area: demos; 200 | display: flex; 201 | gap: 1rem; 202 | } 203 | 204 | .intro-grid-wrap { 205 | grid-area: main; 206 | height: 100vh; 207 | } 208 | 209 | .intro-grid { 210 | grid-area: main; 211 | display: grid; 212 | grid-template-columns: repeat(2,1fr); 213 | width: 100%; 214 | gap: 2vw; 215 | padding: 2vw 2vw 4rem; 216 | } 217 | 218 | .intro-grid--labels { 219 | padding-top: 0.75rem; 220 | grid-template-rows: auto; 221 | align-self: start; 222 | padding-bottom: 0; 223 | display: none; 224 | } 225 | 226 | .intro-grid--images { 227 | padding-top: 3rem; 228 | height: 100vh; 229 | } 230 | 231 | .intro-grid--slider { 232 | --slider-item-height: 60vh; 233 | --slider-item-gap: 7vh; 234 | display: flex; 235 | flex-direction: column; 236 | align-items: center; 237 | height: calc(var(--slider-item-height) + var(--slider-item-gap)); /* item height plus gap */ 238 | gap: 7vh; 239 | padding: 0; 240 | align-self: center; 241 | } 242 | 243 | .intro-grid--images.intro-grid--thumbs { 244 | padding-top: 1.85rem; 245 | padding-bottom: 0; 246 | grid-template-columns: repeat(20,1fr); 247 | grid-template-rows: auto 5vh 1fr 10vh; 248 | column-gap: 1.5vw; 249 | } 250 | 251 | .intro-grid--thumbs .intro-grid__img { 252 | grid-area: auto; 253 | aspect-ratio: 0.75; 254 | cursor: not-allowed; 255 | } 256 | 257 | .intro-grid--thumbs .intro-grid__img--current { 258 | grid-area: 3 / 1 / 4 / -1; 259 | justify-self: center; 260 | pointer-events: none; 261 | } 262 | 263 | .intro-grid--slider .intro-grid__label { 264 | position: absolute; 265 | } 266 | 267 | .intro-grid__img { 268 | background-size: cover; 269 | background-position: 50% 20%; 270 | cursor: pointer; 271 | will-change: transform, filter; 272 | transform: translateZ(0.1px); 273 | } 274 | 275 | .intro-grid--slider .intro-grid__img { 276 | height: var(--slider-item-height); 277 | aspect-ratio: 0.75; 278 | flex: none; 279 | } 280 | 281 | .intro-grid--scatter { 282 | width: 200%; 283 | height: 200vh; 284 | padding: 0; 285 | } 286 | 287 | .intro-grid--scatter .intro-grid__img { 288 | max-width: 20vw; 289 | max-height: 50vh; 290 | } 291 | 292 | .intro-grid--scatter .intro-grid__img--current { 293 | width: 30vw; 294 | height: 70vh; 295 | max-width: none; 296 | max-height: none; 297 | } 298 | 299 | .intro-title { 300 | grid-area: main; 301 | align-self: center; 302 | justify-self: center; 303 | text-align: center; 304 | cursor: default; 305 | pointer-events: none; 306 | } 307 | 308 | .intro-title__main, 309 | .slider-title__main { 310 | margin: 0; 311 | font-size: clamp(1rem, 7vw, 10rem); 312 | font-family: organetto-variable, sans-serif; 313 | font-variation-settings: "wdth" 100, "wght" 400; 314 | } 315 | 316 | .intro-title__main > span, 317 | .slider-title__main > span { 318 | background-image: linear-gradient(45deg, var(--title-gr-1), var(--title-gr-2)); 319 | background-size: 100%; 320 | background-repeat: repeat; 321 | -webkit-background-clip: text; 322 | -webkit-text-fill-color: transparent; 323 | -moz-background-clip: text; 324 | -moz-text-fill-color: transparent; 325 | } 326 | 327 | .intro-title__sub { 328 | font-family: microgramma-extended, sans-serif; 329 | font-weight: 500; 330 | font-style: normal; 331 | font-size: clamp(1rem, 4vw, 2rem); 332 | display: block; 333 | } 334 | 335 | .slider-title { 336 | opacity: 0; 337 | pointer-events: none; 338 | grid-area: main; 339 | align-self: center; 340 | justify-self: center; 341 | position: relative; 342 | } 343 | 344 | .slider-title__main { 345 | font-size: clamp(1rem, 6vw, 9rem); 346 | } 347 | 348 | .slider-title__desc { 349 | left: 10vw; 350 | position: absolute; 351 | margin: 0; 352 | color: var(--color-desc); 353 | max-width: 200px; 354 | } 355 | 356 | .controls { 357 | position: absolute; 358 | padding: 2rem; 359 | top: 0; 360 | right: 0; 361 | display: flex; 362 | text-transform: uppercase; 363 | color: var(--color-link); 364 | gap: 1rem; 365 | pointer-events: none; 366 | z-index: 100; 367 | } 368 | 369 | .controls--open { 370 | pointer-events: auto; 371 | } 372 | 373 | .controls button { 374 | text-transform: uppercase; 375 | color: var(--color-link); 376 | } 377 | 378 | .close { 379 | border: 1px solid var(--color-link); 380 | width: 3rem; 381 | height: 3rem; 382 | display: grid; 383 | place-items: center; 384 | border-radius: 50%; 385 | opacity: 0; 386 | } 387 | 388 | .nav { 389 | padding: 0 1.5rem; 390 | border: 1px solid var(--color-link); 391 | align-items: center; 392 | gap: 1rem; 393 | border-radius: 2rem; 394 | opacity: 0; 395 | display: none; 396 | } 397 | 398 | .nav__item { 399 | cursor: not-allowed; 400 | } 401 | 402 | @media screen and (min-width: 53em) { 403 | .frame { 404 | position: fixed; 405 | height: 100vh; 406 | grid-template-columns: auto auto auto 1fr; 407 | grid-template-rows: auto auto; 408 | grid-template-areas: '... ... ... ...' 'title prev sponsor demos'; 409 | align-content: space-between; 410 | justify-items: start; 411 | grid-gap: 2rem; 412 | padding: 0.75rem; 413 | } 414 | .frame__demos { 415 | justify-self: end; 416 | } 417 | .intro-grid { 418 | grid-template-columns: repeat(10,1fr); 419 | } 420 | .intro-grid--labels { 421 | display: grid; 422 | } 423 | .intro-grid--images { 424 | grid-template-rows: 1fr 1fr 1fr 1fr; 425 | } 426 | .intro-grid__img { 427 | background-position: 50% 50%; 428 | } 429 | .pos-1 { grid-area: 1 / 1; } 430 | .pos-2 { grid-area: 1 / 2; } 431 | .pos-3 { grid-area: 1 / 4; } 432 | .pos-4 { grid-area: 1 / 5; } 433 | .pos-5 { grid-area: 1 / 6; } 434 | .pos-6 { grid-area: 1 / 7; } 435 | .pos-7 { grid-area: 1 / 9; } 436 | .pos-8 { grid-area: 1 / 10; } 437 | .pos-9 { grid-area: 1 / 7; } 438 | .pos-10 { grid-area: 4 / 9; } 439 | .pos-11 { grid-area: 1 / 1; } 440 | .pos-12 { grid-area: 2 / 2; } 441 | .pos-13 { grid-area: 3 / 1; } 442 | .pos-14 { grid-area: 3 / 4; } 443 | .pos-15 { grid-area: 4 / 4; } 444 | .pos-16 { grid-area: 1 / 5; } 445 | .pos-17 { grid-area: 2 / 5; } 446 | .pos-18 { grid-area: 4 / 5; } 447 | .pos-19 { grid-area: 3 / 6; } 448 | .pos-20 { grid-area: 2 / 9; } 449 | .pos-21 { grid-area: 2 / 10; } 450 | .pos-22 { grid-area: 3 / 10; } 451 | .nav { 452 | display: flex; 453 | } 454 | } 455 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/favicon.ico -------------------------------------------------------------------------------- /img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/1.jpg -------------------------------------------------------------------------------- /img/10.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/10.jpg -------------------------------------------------------------------------------- /img/11.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/11.jpg -------------------------------------------------------------------------------- /img/12.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/12.jpg -------------------------------------------------------------------------------- /img/13.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/13.jpg -------------------------------------------------------------------------------- /img/14.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/14.jpg -------------------------------------------------------------------------------- /img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/2.jpg -------------------------------------------------------------------------------- /img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/3.jpg -------------------------------------------------------------------------------- /img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/4.jpg -------------------------------------------------------------------------------- /img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/5.jpg -------------------------------------------------------------------------------- /img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/6.jpg -------------------------------------------------------------------------------- /img/7.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/7.jpg -------------------------------------------------------------------------------- /img/8.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/8.jpg -------------------------------------------------------------------------------- /img/9.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/GridToSlider/1d8b2abb52ba9207459d1b2ee6ac372f429ef8de/img/9.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Grid to Slideshow Animations | Demo 1 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |

Grid to Slideshow Switch

21 | 22 | Back to the article 23 | 24 | 25 | 26 |
27 | Previous demo 28 | 34 |
35 |
36 | I 37 | II 38 | III 39 | IV 40 | V 41 | VI 42 | VII 43 | VIII 44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |

Nale Aby

63 | Prompt Fashion 64 |
65 |
66 |

Collection

67 |

The collection is a celebration of beauty, sustainability, and ethical production.

68 |
69 |
70 | 71 | 78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /index2.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Grid to Slideshow Animations | Demo 2 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |

Grid to Slideshow Switch

21 | 22 | Back to the article 23 | 24 | 25 | 26 |
27 | Previous demo 28 | 34 |
35 |
36 | I 37 | II 38 | III 39 | IV 40 | V 41 | VI 42 | VII 43 | VIII 44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |

Duo Naval

63 | Prompt Fashion 64 |
65 |
66 |

Collection

67 |

The collection is a celebration of beauty, sustainability, and ethical production.

68 |
69 |
70 | 71 | 78 |
79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | -------------------------------------------------------------------------------- /index3.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Grid to Slideshow Animations | Demo 3 | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |

Grid to Slideshow Switch

21 | 22 | Back to the article 23 | 24 | 25 | 26 |
27 | Previous demo 28 | 34 |
35 |
36 | I 37 | II 38 | III 39 | IV 40 | V 41 | VI 42 | VII 43 | VIII 44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |

Kaban

65 | Prompt Fashion 66 |
67 |
68 |

Collection

69 |

The collection is a celebration of beauty, sustainability, and ethical production.

70 |
71 |
72 | 73 | 80 |
81 |
82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /js/Flip.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Flip 3.11.5 3 | * https://greensock.com 4 | * 5 | * @license Copyright 2023, GreenSock. All rights reserved. 6 | * Subject to the terms at https://greensock.com/standard-license or for Club GreenSock 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 p(t){var e=t.ownerDocument||t;!(w in t.style)&&"msTransform"in t.style&&(k=(w="msTransform")+"Origin");for(;e.parentNode&&(e=e.parentNode););if(y=window,d=new M,e){r=(g=e).documentElement,b=e.body,(a=g.createElementNS("http://www.w3.org/2000/svg","g")).style.transform="none";var i=e.createElement("div"),n=e.createElement("div");b.appendChild(i),i.appendChild(n),i.style.position="static",i.style[w]="translate3d(0,0,1px)",m=n.offsetParent!==i,b.removeChild(i)}return e}function t(){return y.pageYOffset||g.scrollTop||r.scrollTop||b.scrollTop||0}function u(){return y.pageXOffset||g.scrollLeft||r.scrollLeft||b.scrollLeft||0}function v(t){return t.ownerSVGElement||("svg"===(t.tagName+"").toLowerCase()?t:null)}function x(t,e){if(t.parentNode&&(g||p(t))){var i=v(t),n=i?i.getAttribute("xmlns")||"http://www.w3.org/2000/svg":"http://www.w3.org/1999/xhtml",r=i?e?"rect":"g":"div",a=2!==e?0:100,s=3===e?100:0,o="position:absolute;display:block;pointer-events:none;margin:0;padding:0;",l=g.createElementNS?g.createElementNS(n.replace(/^https/,"http"),r):g.createElement(r);return e&&(i?(f=f||x(t),l.setAttribute("width",.01),l.setAttribute("height",.01),l.setAttribute("transform","translate("+a+","+s+")"),f.appendChild(l)):(c||((c=x(t)).style.cssText=o),l.style.cssText=o+"width:0.1px;height:0.1px;top:"+s+"px;left:"+a+"px",c.appendChild(l))),l}throw"Need document and parent."}function z(t){var e,i=t.getCTM();return i||(e=t.style[w],t.style[w]="none",t.appendChild(a),i=a.getCTM(),t.removeChild(a),e?t.style[w]=e:t.style.removeProperty(w.replace(/([A-Z])/g,"-$1").toLowerCase())),i||d.clone()}function A(t,e){var i,n,r,a,s,o,l=v(t),u=t===l,p=l?C:E,h=t.parentNode;if(t===y)return t;if(p.length||p.push(x(t,1),x(t,2),x(t,3)),i=l?f:c,l)u?(a=-(r=z(t)).e/r.a,s=-r.f/r.d,n=d):t.getBBox?(r=t.getBBox(),a=(n=(n=t.transform?t.transform.baseVal:{}).numberOfItems?1=o;t&&!n&&ha(H,!x),L&&X(e,L,t?"remove":"add")})},k&&(S=H.filter(function(t){return!t.sd&&!t.a.isVisible&&t.b.isVisible}).map(function(t){return t.a.element})),tt?(S&&(y=tt._abs).push.apply(y,ka(H,S)),tt._run.push(m)):(S&&la(ka(H,S)),m());var K=tt?tt.timeline:j;return K.revert=function(){return lt(K,1)},K}function Da(t){for(var e,i=t.idLookup={},n=t.alt={},r=t.elementStates,a=r.length;a--;)i[(e=r[a]).id]?n[e.id]=e:i[e.id]=e}var I,Q,tt,s,o,P,T,l,n,h=1,F={},O=180/Math.PI,N=Math.PI/180,D={},Y={},et={},it=S("onStart,onUpdate,onComplete,onReverseComplete,onInterrupt"),nt=S("transform,transformOrigin,width,height,position,top,left,opacity,zIndex,maxWidth,maxHeight,minWidth,minHeight"),rt={zIndex:1,kill:1,simple:1,spin:1,clearProps:1,targets:1,toggleClass:1,onComplete:1,onUpdate:1,onInterrupt:1,onStart:1,delay:1,repeat:1,repeatDelay:1,yoyo:1,scale:1,fade:1,absolute:1,props:1,onEnter:1,onLeave:1,custom:1,paused:1,nested:1,prune:1,absoluteOnLeave:1},at={zIndex:1,simple:1,clearProps:1,scale:1,absolute:1,fitChild:1,getVars:1,props:1},st={},j="paddingTop,paddingRight,paddingBottom,paddingLeft,gridArea,transition".split(","),R=function _parseElementState(t,e,i,n){return t instanceof pt?t:t instanceof ut?function _findElStateInState(t,e){return e&&t.idLookup[R(e).id]||t.elementStates[0]}(t,n):new pt("string"==typeof t?V(t)||console.warn(t+" not found"):t,e,i)},ot=function _fit(t,e,i,n,r,a){var s,o,l,u,p,h,c,f=t.element,d=t.cache,m=t.parent,g=t.x,v=t.y,y=e.width,x=e.height,b=e.scaleX,w=e.scaleY,S=e.rotation,k=e.bounds,_=a&&T&&T(f,"transform"),C=t,V=e.matrix,E=V.e,M=V.f,B=t.bounds.width!==k.width||t.bounds.height!==k.height||t.scaleX!==b||t.scaleY!==w||t.rotation!==S,F=!B&&t.simple&&e.simple&&!r;return F||!m?(b=w=1,S=s=0):(h=(p=function _getInverseGlobalMatrix(t){var e=t._gsap||Q.core.getCache(t);return e.gmCache===Q.ticker.frame?e.gMatrix:(e.gmCache=Q.ticker.frame,e.gMatrix=getGlobalMatrix(t,!0,!1,!0))}(m)).clone().multiply(e.ctm?e.matrix.clone().multiply(e.ctm):e.matrix),S=W(Math.atan2(h.b,h.a)*O),s=W(Math.atan2(h.c,h.d)*O+S)%360,b=Math.sqrt(Math.pow(h.a,2)+Math.pow(h.b,2)),w=Math.sqrt(Math.pow(h.c,2)+Math.pow(h.d,2))*Math.cos(s*N),r&&(r=I(r)[0],u=Q.getProperty(r),c=r.getBBox&&"function"==typeof r.getBBox&&r.getBBox(),C={scaleX:u("scaleX"),scaleY:u("scaleY"),width:c?c.width:Math.ceil(parseFloat(u("width","px"))),height:c?c.height:parseFloat(u("height","px"))}),d.rotation=S+"deg",d.skewX=s+"deg"),i?(b*=y!==C.width&&C.width?y/C.width:1,w*=x!==C.height&&C.height?x/C.height:1,d.scaleX=b,d.scaleY=w):(y=P(y*b/C.scaleX,0),x=P(x*w/C.scaleY,0),f.style.width=y+"px",f.style.height=x+"px"),n&&pa(f,e.props),F||!m?(g+=E-t.matrix.e,v+=M-t.matrix.f):B||m!==e.parent?(d.renderTransform(1,d),h=getGlobalMatrix(r||f,!1,!1,!0),o=p.apply({x:h.e,y:h.f}),g+=(l=p.apply({x:E,y:M})).x-o.x,v+=l.y-o.y):(p.e=p.f=0,g+=(l=p.apply({x:E-t.matrix.e,y:M-t.matrix.f})).x,v+=l.y),g=P(g,.02),v=P(v,.02),!a||a instanceof pt?(d.x=g+"px",d.y=v+"px",d.renderTransform(1,d)):_&&_.revert(),a&&(a.x=g,a.y=v,a.rotation=S,a.skewX=s,i?(a.scaleX=b,a.scaleY=w):(a.width=y,a.height=x)),a||d},G=[],H="width,height,overflowX,overflowY".split(","),lt=function _killFlip(t,e){if(t&&t.progress()<1&&!t.paused())return e&&(function _interrupt(t){t.vars.onInterrupt&&t.vars.onInterrupt.apply(t,t.vars.onInterruptParams||[]),t.getChildren(!0,!1,!0).forEach(_interrupt)}(t),e<2&&t.progress(1),t.kill()),!0},ut=((n=FlipState.prototype).update=function update(t){var e=this;return this.elementStates=this.targets.map(function(t){return new pt(t,e.props,e.simple)}),Da(this),this.interrupt(t),this.recordInlineStyles(),this},n.clear=function clear(){return this.targets.length=this.elementStates.length=0,Da(this),this},n.fit=function fit(t,e,i){for(var n,r,a=ea(this.elementStates.slice(0),!1,!0),s=(t||this).idLookup,o=0;o .intro-grid__label > .oh__inner')]; 11 | 12 | // The grid title 13 | const gridTitle = { 14 | main: document.querySelector('.intro-title > .intro-title__main > .oh__inner'), 15 | sub: document.querySelector('.intro-title > .intro-title__sub > .oh__inner'), 16 | }; 17 | 18 | // The slider title 19 | const sliderTitle = { 20 | el: document.querySelector('.slider-title'), 21 | main: document.querySelector('.slider-title > .slider-title__main > .oh__inner'), 22 | desc: document.querySelector('.slider-title > .slider-title__desc'), 23 | }; 24 | 25 | // Controls element 26 | const controls = document.querySelector('.controls'); 27 | // Controls close button and nav elements 28 | const closeCtrl = controls.querySelector('button.close'); 29 | const nav = controls.querySelector('nav.nav'); 30 | 31 | // Clicked image's index value 32 | let current = -1; 33 | // Check if the animation is in progress 34 | let isAnimating = false; 35 | // grid || slider 36 | let mode = 'grid'; 37 | 38 | // Show the slider 39 | const showSlider = image => { 40 | if ( isAnimating || mode === 'slider' ) return; 41 | isAnimating = true; 42 | mode = 'slider'; 43 | 44 | const DURATION = 1; 45 | const EASE = 'power4.inOut'; 46 | 47 | current = gridImages.indexOf(image); 48 | 49 | gsap 50 | .timeline({ 51 | defaults: { 52 | duration: DURATION, 53 | ease: EASE 54 | }, 55 | onComplete: () => isAnimating = false 56 | }) 57 | .addLabel('start', 0) 58 | .to(Object.values(gridTitle), { 59 | yPercent: -100 60 | }, 'start') 61 | .to(gridLabels, { 62 | yPercent: -100 63 | }, 'start') 64 | .to(image, {filter: 'brightness(100%) hue-rotate(0deg)'}, 'start') 65 | .add(() => { 66 | // Save current state of all images 67 | const flipstate = Flip.getState(gridImages); 68 | // Change layout 69 | introGrid.classList.add('intro-grid--slider'); 70 | // and position the introSlider at the center of the current image 71 | gsap.set(introGrid, { 72 | yPercent: -100*current 73 | }); 74 | // Animate all 75 | Flip.from(flipstate, { 76 | duration: DURATION, 77 | ease: EASE, 78 | absolute: true, 79 | stagger: { 80 | each: 0.02, 81 | from: current 82 | }, 83 | simple: true, 84 | prune: true, 85 | }); 86 | }, 'start') 87 | .set(sliderTitle.el, { 88 | opacity: 1 89 | }, 'start') 90 | .fromTo([sliderTitle.main, sliderTitle.desc], { 91 | yPercent: pos => pos ? 240 : 100, 92 | opacity: pos => pos ? 0 : 1 93 | }, { 94 | yPercent: 0, 95 | opacity: 1 96 | }, 'start') 97 | .add(() => { 98 | controls.classList.add('controls--open'); 99 | }, 'start') 100 | .fromTo([closeCtrl, nav], { 101 | scale: 0 102 | }, { 103 | opacity: 1, 104 | scale: 1, 105 | stagger: 0.02 106 | }, 'start') 107 | }; 108 | 109 | // Hide the slider 110 | const hideSlider = () => { 111 | if ( isAnimating || mode === 'grid' ) return; 112 | isAnimating = true; 113 | mode = 'grid'; 114 | 115 | const DURATION = 1; 116 | const EASE = 'power4.inOut'; 117 | 118 | gsap 119 | .timeline({ 120 | defaults: { 121 | duration: DURATION, 122 | ease: EASE 123 | }, 124 | onComplete: () => isAnimating = false 125 | }) 126 | .to([closeCtrl, nav], { 127 | opacity: 0, 128 | scale: 0 129 | }, 'start') 130 | .add(() => { 131 | controls.classList.remove('controls--open'); 132 | }, 'start') 133 | .to([sliderTitle.main, sliderTitle.desc], { 134 | yPercent: pos => pos ? 150 : 100, 135 | opacity: pos => pos ? 0 : 1, 136 | onComplete: () => gsap.set(sliderTitle.el, {opacity: 0}) 137 | }, 'start') 138 | .add(() => { 139 | // Save current state of all images 140 | const flipstate = Flip.getState(gridImages, {props: 'filter'}); 141 | // Change layout 142 | introGrid.classList.remove('intro-grid--slider'); 143 | gsap.set(gridImages[current], {filter: 'brightness(100%) hue-rotate(0deg)'}); 144 | gsap.set(introGrid, { 145 | yPercent: 0 146 | }); 147 | // Animate all 148 | Flip.from(flipstate, { 149 | duration: DURATION, 150 | ease: EASE, 151 | absolute: true, 152 | stagger: { 153 | each: 0.02, 154 | from: current 155 | }, 156 | simple: true, 157 | prune: true, 158 | }); 159 | }, 'start') 160 | .to([gridLabels, Object.values(gridTitle)], { 161 | yPercent: 0 162 | }, 'start') 163 | }; 164 | 165 | // Grid images click event 166 | gridImages.forEach(image => { 167 | image.addEventListener('click', () => showSlider(image)); 168 | 169 | image.addEventListener('mouseenter', () => { 170 | if ( mode === 'slider' ) return; 171 | gsap.fromTo(image, { 172 | filter: 'brightness(100%) hue-rotate(0deg)' 173 | }, { 174 | duration: 1, 175 | ease: 'power4', 176 | filter: 'brightness(200%) hue-rotate(130deg)' 177 | }); 178 | }); 179 | 180 | image.addEventListener('mouseleave', () => { 181 | if ( mode === 'slider' ) return; 182 | gsap.to(image, { 183 | duration: 1, 184 | ease: 'power4', 185 | filter: 'brightness(100%) hue-rotate(0deg)' 186 | }); 187 | }); 188 | 189 | closeCtrl.addEventListener('click', () => hideSlider()); 190 | }); 191 | 192 | // Preload images then remove loader (loading class) from body 193 | preloadImages('.intro-grid__img').then(() => document.body.classList.remove('loading')); -------------------------------------------------------------------------------- /js/demo2/index.js: -------------------------------------------------------------------------------- 1 | import { preloadImages } from '../utils.js'; 2 | 3 | // Grid 4 | const introGrid = document.querySelector('.intro-grid--images'); 5 | 6 | // The grid images 7 | const gridImages = [...introGrid.querySelectorAll('.intro-grid__img')]; 8 | 9 | // The grid labels 10 | const gridLabels = [...document.querySelectorAll('.intro-grid--labels > .intro-grid__label > .oh__inner')]; 11 | 12 | // The grid title 13 | const gridTitle = { 14 | main: document.querySelector('.intro-title > .intro-title__main > .oh__inner'), 15 | sub: document.querySelector('.intro-title > .intro-title__sub > .oh__inner'), 16 | }; 17 | 18 | // The slider title 19 | const sliderTitle = { 20 | el: document.querySelector('.slider-title'), 21 | main: document.querySelector('.slider-title > .slider-title__main > .oh__inner'), 22 | desc: document.querySelector('.slider-title > .slider-title__desc'), 23 | }; 24 | 25 | // Controls element 26 | const controls = document.querySelector('.controls'); 27 | // Controls close button and nav elements 28 | const closeCtrl = controls.querySelector('button.close'); 29 | const nav = controls.querySelector('nav.nav'); 30 | 31 | // Clicked image's index value 32 | let current = -1; 33 | // Check if the animation is in progress 34 | let isAnimating = false; 35 | // grid || slider 36 | let mode = 'grid'; 37 | 38 | // Show the slider 39 | const showSlider = image => { 40 | if ( isAnimating || mode === 'slider' ) return; 41 | isAnimating = true; 42 | mode = 'slider'; 43 | 44 | const DURATION = 1; 45 | const EASE = 'power4.inOut'; 46 | 47 | current = gridImages.indexOf(image); 48 | 49 | gsap 50 | .timeline({ 51 | defaults: { 52 | duration: DURATION, 53 | ease: EASE 54 | }, 55 | onComplete: () => isAnimating = false 56 | }) 57 | .addLabel('start', 0) 58 | .to(Object.values(gridTitle), { 59 | yPercent: -100 60 | }, 'start') 61 | .to(gridLabels, { 62 | yPercent: -100 63 | }, 'start') 64 | .to(image, {filter: 'brightness(100%) hue-rotate(0deg)'}, 'start') 65 | .add(() => { 66 | // Save current state of all images 67 | const flipstate = Flip.getState(gridImages); 68 | // Change layout 69 | introGrid.classList.add('intro-grid--thumbs'); 70 | image.classList.add('intro-grid__img--current'); 71 | // Animate all 72 | Flip.from(flipstate, { 73 | duration: DURATION, 74 | ease: EASE, 75 | absolute: true, 76 | stagger: { 77 | each: 0.02, 78 | from: 'start' 79 | }, 80 | simple: true, 81 | prune: true, 82 | }); 83 | }, 'start') 84 | .set(sliderTitle.el, { 85 | opacity: 1 86 | }, 'start') 87 | .fromTo([sliderTitle.main, sliderTitle.desc], { 88 | yPercent: pos => pos ? 240 : 100, 89 | opacity: pos => pos ? 0 : 1 90 | }, { 91 | yPercent: 0, 92 | opacity: 1 93 | }, 'start') 94 | .add(() => { 95 | controls.classList.add('controls--open'); 96 | }, 'start') 97 | .fromTo([closeCtrl, nav], { 98 | scale: 0 99 | }, { 100 | opacity: 1, 101 | scale: 1, 102 | stagger: 0.02 103 | }, 'start') 104 | }; 105 | 106 | // Hide the slider 107 | const hideSlider = () => { 108 | if ( isAnimating || mode === 'grid' ) return; 109 | isAnimating = true; 110 | mode = 'grid'; 111 | 112 | const DURATION = 1; 113 | const EASE = 'power4.inOut'; 114 | 115 | gsap 116 | .timeline({ 117 | defaults: { 118 | duration: DURATION, 119 | ease: EASE 120 | }, 121 | onComplete: () => isAnimating = false 122 | }) 123 | .to([closeCtrl, nav], { 124 | opacity: 0, 125 | scale: 0 126 | }, 'start') 127 | .add(() => { 128 | controls.classList.remove('controls--open'); 129 | }, 'start') 130 | .to([sliderTitle.main, sliderTitle.desc], { 131 | yPercent: pos => pos ? 150 : 100, 132 | opacity: pos => pos ? 0 : 1, 133 | onComplete: () => gsap.set(sliderTitle.el, {opacity: 0}) 134 | }, 'start') 135 | .add(() => { 136 | // Save current state of all images 137 | const flipstate = Flip.getState(gridImages, {props: 'filter'}); 138 | // Change layout 139 | introGrid.classList.remove('intro-grid--thumbs'); 140 | gridImages[current].classList.remove('intro-grid__img--current'); 141 | gsap.set(gridImages[current], {filter: 'brightness(100%) hue-rotate(0deg)'}); 142 | 143 | // Animate all 144 | Flip.from(flipstate, { 145 | duration: DURATION, 146 | ease: EASE, 147 | absolute: true, 148 | stagger: { 149 | each: 0.02, 150 | from: current 151 | }, 152 | simple: true, 153 | prune: true, 154 | }); 155 | }, 'start') 156 | .to([gridLabels, Object.values(gridTitle)], { 157 | yPercent: 0 158 | }, 'start') 159 | }; 160 | 161 | // Grid images click event 162 | gridImages.forEach(image => { 163 | image.addEventListener('click', () => showSlider(image)); 164 | 165 | image.addEventListener('mouseenter', () => { 166 | if ( mode === 'slider' ) return; 167 | gsap.fromTo(image, { 168 | filter: 'brightness(100%) hue-rotate(0deg)' 169 | }, { 170 | duration: 1, 171 | ease: 'power4', 172 | filter: 'brightness(200%) hue-rotate(130deg)' 173 | }); 174 | }); 175 | 176 | image.addEventListener('mouseleave', () => { 177 | if ( mode === 'slider' ) return; 178 | gsap.to(image, { 179 | duration: 1, 180 | ease: 'power4', 181 | filter: 'brightness(100%) hue-rotate(0deg)' 182 | }); 183 | }); 184 | 185 | closeCtrl.addEventListener('click', () => hideSlider()); 186 | }); 187 | 188 | // Preload images then remove loader (loading class) from body 189 | preloadImages('.intro-grid__img').then(() => document.body.classList.remove('loading')); -------------------------------------------------------------------------------- /js/demo3/index.js: -------------------------------------------------------------------------------- 1 | import { preloadImages } from '../utils.js'; 2 | 3 | // Grid 4 | const introGrid = document.querySelector('.intro-grid--images'); 5 | 6 | // The grid images 7 | const gridImages = [...introGrid.querySelectorAll('.intro-grid__img')]; 8 | 9 | // The grid labels 10 | const gridLabels = [...document.querySelectorAll('.intro-grid--labels > .intro-grid__label > .oh__inner')]; 11 | 12 | // The grid title 13 | const gridTitle = { 14 | main: document.querySelector('.intro-title > .intro-title__main > .oh__inner'), 15 | sub: document.querySelector('.intro-title > .intro-title__sub > .oh__inner'), 16 | }; 17 | 18 | // The slider title 19 | const sliderTitle = { 20 | el: document.querySelector('.slider-title'), 21 | main: document.querySelector('.slider-title > .slider-title__main > .oh__inner'), 22 | desc: document.querySelector('.slider-title > .slider-title__desc'), 23 | }; 24 | 25 | // Controls element 26 | const controls = document.querySelector('.controls'); 27 | // Controls close button and nav elements 28 | const closeCtrl = controls.querySelector('button.close'); 29 | const nav = controls.querySelector('nav.nav'); 30 | 31 | // Clicked image's index value 32 | let current = -1; 33 | // Check if the animation is in progress 34 | let isAnimating = false; 35 | // grid || slider 36 | let mode = 'grid'; 37 | 38 | // Show the slider 39 | const showSlider = image => { 40 | if ( isAnimating || mode === 'slider' ) return; 41 | isAnimating = true; 42 | mode = 'slider'; 43 | 44 | const DURATION = 1; 45 | const EASE = 'power4.inOut'; 46 | 47 | current = gridImages.indexOf(image); 48 | 49 | gsap 50 | .timeline({ 51 | defaults: { 52 | duration: DURATION, 53 | ease: EASE 54 | }, 55 | onComplete: () => isAnimating = false 56 | }) 57 | .addLabel('start', 0) 58 | .to(Object.values(gridTitle), { 59 | yPercent: -100 60 | }, 'start') 61 | .to(gridLabels, { 62 | yPercent: -100 63 | }, 'start') 64 | .to(image, {filter: 'brightness(100%) hue-rotate(0deg)'}, 'start') 65 | .add(() => { 66 | // Save current state of all images 67 | const flipstate = Flip.getState(gridImages); 68 | // Change layout 69 | introGrid.classList.add('intro-grid--scatter'); 70 | image.classList.add('intro-grid__img--current'); 71 | gsap.set(introGrid, { 72 | x: window.innerWidth/2 - (image.getBoundingClientRect()['left'] + image.offsetWidth/2), 73 | y: window.innerHeight/2 - (image.getBoundingClientRect()['top'] + image.offsetHeight/2) 74 | }); 75 | 76 | // Animate all 77 | Flip.from(flipstate, { 78 | duration: DURATION, 79 | ease: EASE, 80 | absolute: true, 81 | stagger: { 82 | each: 0.015, 83 | from: current 84 | }, 85 | simple: true, 86 | prune: true, 87 | }); 88 | }, 'start') 89 | .set(sliderTitle.el, { 90 | opacity: 1 91 | }, 'start') 92 | .fromTo([sliderTitle.main, sliderTitle.desc], { 93 | yPercent: pos => pos ? 240 : 100, 94 | opacity: pos => pos ? 0 : 1 95 | }, { 96 | yPercent: 0, 97 | opacity: 1 98 | }, 'start') 99 | .add(() => { 100 | controls.classList.add('controls--open'); 101 | }, 'start') 102 | .fromTo([closeCtrl, nav], { 103 | scale: 0 104 | }, { 105 | opacity: 1, 106 | scale: 1, 107 | stagger: 0.04 108 | }, 'start') 109 | }; 110 | 111 | // Hide the slider 112 | const hideSlider = () => { 113 | if ( isAnimating || mode === 'grid' ) return; 114 | isAnimating = true; 115 | mode = 'grid'; 116 | 117 | const DURATION = 1; 118 | const EASE = 'power4.inOut'; 119 | 120 | gsap 121 | .timeline({ 122 | defaults: { 123 | duration: DURATION, 124 | ease: EASE 125 | }, 126 | onComplete: () => isAnimating = false 127 | }) 128 | .to([closeCtrl, nav], { 129 | opacity: 0, 130 | scale: 0 131 | }, 'start') 132 | .add(() => { 133 | controls.classList.remove('controls--open'); 134 | }, 'start') 135 | .to([sliderTitle.main, sliderTitle.desc], { 136 | yPercent: pos => pos ? 150 : 100, 137 | opacity: pos => pos ? 0 : 1, 138 | onComplete: () => gsap.set(sliderTitle.el, {opacity: 0}) 139 | }, 'start') 140 | .add(() => { 141 | // Save current state of all images 142 | const flipstate = Flip.getState(gridImages, {props: 'filter'}); 143 | // Change layout 144 | introGrid.classList.remove('intro-grid--scatter'); 145 | gridImages[current].classList.remove('intro-grid__img--current'); 146 | gsap.set(gridImages[current], {filter: 'brightness(100%) hue-rotate(0deg)'}); 147 | gsap.set(introGrid, { 148 | x: 0, 149 | y: 0 150 | }); 151 | 152 | // Animate all 153 | Flip.from(flipstate, { 154 | duration: DURATION, 155 | ease: EASE, 156 | absolute: true, 157 | stagger: { 158 | each: 0.02, 159 | from: current 160 | }, 161 | simple: true, 162 | prune: true, 163 | }); 164 | }, 'start') 165 | .to([gridLabels, Object.values(gridTitle)], { 166 | yPercent: 0 167 | }, 'start') 168 | }; 169 | 170 | // Grid images click event 171 | gridImages.forEach(image => { 172 | image.addEventListener('click', () => showSlider(image)); 173 | 174 | image.addEventListener('mouseenter', () => { 175 | if ( mode === 'slider' ) return; 176 | gsap.fromTo(image, { 177 | filter: 'brightness(100%) hue-rotate(0deg)' 178 | }, { 179 | duration: 1, 180 | ease: 'power4', 181 | filter: 'brightness(200%) hue-rotate(130deg)' 182 | }); 183 | }); 184 | 185 | image.addEventListener('mouseleave', () => { 186 | if ( mode === 'slider' ) return; 187 | gsap.to(image, { 188 | duration: 1, 189 | ease: 'power4', 190 | filter: 'brightness(100%) hue-rotate(0deg)' 191 | }); 192 | }); 193 | 194 | closeCtrl.addEventListener('click', () => hideSlider()); 195 | }); 196 | 197 | // Preload images then remove loader (loading class) from body 198 | preloadImages('.intro-grid__img').then(() => document.body.classList.remove('loading')); -------------------------------------------------------------------------------- /js/gsap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * GSAP 3.11.5 3 | * https://greensock.com 4 | * 5 | * @license Copyright 2023, GreenSock. All rights reserved. 6 | * Subject to the terms at https://greensock.com/standard-license or for Club GreenSock 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))&&Pe}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 qt(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),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&&(B?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(!!B),t.progress()<1&&St(t,"onInterrupt"),t}function wb(t){if(x()){var e=(t=!t.name&&t.default||t).name,r=s(t),i=e&&!r&&t.init?function(){this._props=[]}:t,n={init:T,render:fe,add:Qt,kill:_e,modifier:pe,rawVars:0},a={targetTest:0,get:0,getSetter:re,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(Pe,i,ge)}else Ct.push(t)}function zb(t,e,r){return(6*(t+=t<0?1:1>16,e>>8&Pt,e&Pt]:0:Dt.black;if(!p){if(","===e.substr(-1)&&(e=e.substr(0,e.length-1)),Dt[e])p=Dt[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&Pt,p&Pt,parseInt(e.substr(7),16)/255];p=[(e=parseInt(e.substr(1),16))>>16,e>>8&Pt,e&Pt]}else if("hsl"===e.substr(0,3))if(p=d=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 Jt?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=Jt.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===L&&a._time>n?a._time:n,1,1),a._dirty=0}return a._tDur},Timeline.updateRoot=function updateRoot(t){if(L._ts&&(na(L,Ga(t,L)),f=Rt.frame),Rt.frame>=mt){mt+=V.autoSleep||120;var e=L._first;if((!e||!e._ts)&&V.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=Gt(t,a,e,i,n)),!v(t)||t.style&&t.nodeType||Z(t)||J(t))return r(t)?Gt(t,a,e,i,n):t;var o,u={};for(o in t)u[o]=Gt(t[o],a,e,i,n);return u}(e[t],n,a,o,i),i,n,o)&&(i._pt=h=new ge(i._pt,a,t,0,1,u.render,u,0,u.priority),i!==c))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,Wt,Qt=function _addPropTween(t,e,i,n,a,o,u,h,l,f){s(n)&&(n=n(a||0,t,o));var c,d=t[e],p="get"!==i?i:s(d)?l?t[e.indexOf("set")||!s(t["get"+e.substr(3)])?e:"get"+e.substr(3)](l):t[e]():d,_=s(d)?l?ee:te:Zt;if(r(n)&&(~n.indexOf("random(")&&(n=ob(n)),"="===n.charAt(1)&&(!(c=ka(p,n)+(Ya(p)||0))&&0!==c||(n=c))),!f||p!==n||Wt)return isNaN(p*n)||""===n?(d||e in t||Q(e,n),function _addComplexStringPropTween(t,e,r,i,n,a,s){var o,u,h,l,f,c,d,p,_=new ge(this._pt,t,e,0,1,le,null,n),m=0,g=0;for(_.b=r,_.e=i,r+="",(d=~(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++]&&(c=parseFloat(u[g-1])||0,_._pt={_next:_._pt,p:f||1===g?f:",",s:c,c:"="===l.charAt(1)?ka(c,l)-c:parseFloat(l)-c,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(C=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||B||(St(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),z.prototype.invalidate.call(this,t)},e.resetTo=function resetTo(t,e,r,i){d||Rt.wake(),this._ts||this.play();var n,a=Math.min(this._dur,(this._dp._time-this._start)*this._ts);return this._initted||Kt(this,a),n=this._ease(a/this._dur),function _updatePropTweens(t,e,r,i,n,a,s){var o,u,h,l,f=(t._pt&&t._ptCache||(t._ptCache={}))[e];if(!f)for(f=t._ptCache[e]=[],h=t._ptLookup,l=t._targets.length;l--;){if((o=h[l][e])&&o.d&&o.d._pt)for(o=o.d._pt;o&&o.p!==e&&o.fp!==e;)o=o._next;if(!o)return Wt=1,t.vars[e]="+=0",Kt(t,s),Wt=0,1;f.push(o)}for(l=f.length;l--;)(o=(u=f[l])._pt||u).s=!i&&0!==i||n?o.s+(i||0)+a*o.c:i,o.c=r-o.s,u.e&&(u.e=ia(r)+Ya(u.e)),u.b&&(u.b=o.s+Ya(u.b))}(this,t,e,r,i,n,a)?this.resetTo(t,e,r,i):(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,c=t?Mt(t):f,d=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,c))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(~c.indexOf(f[l]))for(u in a=d[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 L.killTweensOf(t,e,r)},Tween}(Ut);qa(Jt.prototype,{_targets:[],_lazy:0,_startAt:0,_op:0,_onInit:0}),ha("staggerTo,staggerFrom,staggerFromTo",function(r){Jt[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)},ee=function _setterFuncWithParam(t,e,r,i){return t[e](i.fp,r)},re=function _getSetter(t,e){return s(t[e])?te:u(t[e])&&t.setAttribute?oc:Zt},se=function _renderPlain(t,e){return e.set(e.t,e.p,Math.round(1e6*(e.s+e.c*t))/1e6,e)},oe=function _renderBoolean(t,e){return e.set(e.t,e.p,!!(e.s+e.c*t),e)},le=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)},fe=function _renderPropTweens(t,e){for(var r=e._pt;r;)r.r(t,r.d),r=r._next},pe=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},_e=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},me=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},ge=(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||se,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=Jt,ot.TimelineLite=ot.TimelineMax=Xt,L=new Xt({sortChildren:!1,defaults:q,autoRemoveChildren:!0,id:"root",smoothChildTiming:!0}),V.stringFilter=Fb;function Dc(t){return(be[t]||xe).map(function(t){return t()})}function Ec(){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/utils.js: -------------------------------------------------------------------------------- 1 | // Preload images 2 | const preloadImages = (selector = 'img') => { 3 | return new Promise((resolve) => { 4 | imagesLoaded(document.querySelectorAll(selector), {background: true}, resolve); 5 | }); 6 | }; 7 | 8 | export { 9 | preloadImages, 10 | }; --------------------------------------------------------------------------------