├── .gitattributes ├── .gitignore ├── LICENSE ├── README.md ├── css └── base.css ├── favicon.ico ├── img ├── 1.jpg ├── 2.jpg ├── 3.jpg ├── 4.jpg ├── 5.jpg └── 6.jpg ├── index.html └── js ├── ScrollTrigger.min.js ├── content.js ├── gsap.min.js ├── imagesloaded.pkgd.min.js ├── index.js ├── lenis.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 | # On-Scroll Pixelated Image Loading Effect 2 | 3 | A recreation of the on-scroll pixelated image loading effect seen on [Felicity Ingram](https://www.felicityingram.com/)'s website. 4 | 5 | ![Onscroll pixel loading](https://tympanus.net/codrops/wp-content/uploads/2023/05/pixelloading.jpg) 6 | 7 | [Article on Codrops](https://tympanus.net/codrops/?p=) 8 | 9 | [Demo](http://tympanus.net/Development/ImagePixelLoading/) 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: #fff; 10 | --color-bg: #a98b9a; 11 | --color-link: #fff; 12 | --color-link-hover: #fff; 13 | --padding-page: 2rem; 14 | } 15 | 16 | body { 17 | margin: 0; 18 | color: var(--color-text); 19 | background-color: var(--color-bg); 20 | font-family: "forma-djr-micro",-apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif; 21 | -webkit-font-smoothing: antialiased; 22 | -moz-osx-font-smoothing: grayscale; 23 | text-transform: uppercase; 24 | overflow-x: hidden; 25 | } 26 | 27 | /* Page Loader */ 28 | .js .loading::before, 29 | .js .loading::after { 30 | content: ''; 31 | position: fixed; 32 | z-index: 1000; 33 | } 34 | 35 | .js .loading::before { 36 | top: 0; 37 | left: 0; 38 | width: 100%; 39 | height: 100%; 40 | background: var(--color-bg); 41 | } 42 | 43 | .js .loading::after { 44 | top: 50%; 45 | left: 50%; 46 | width: 60px; 47 | height: 60px; 48 | margin: -30px 0 0 -30px; 49 | opacity: 0.4; 50 | background: var(--color-link); 51 | animation: loaderAnim 0.7s linear infinite alternate forwards; 52 | 53 | } 54 | 55 | @keyframes loaderAnim { 56 | to { 57 | opacity: 1; 58 | transform: scale3d(0.5,0.5,1); 59 | } 60 | } 61 | 62 | a { 63 | text-decoration: none; 64 | color: var(--color-link); 65 | outline: none; 66 | cursor: pointer; 67 | } 68 | 69 | a:hover { 70 | color: var(--color-link-hover); 71 | outline: none; 72 | } 73 | 74 | /* Better focus styles from https://developer.mozilla.org/en-US/docs/Web/CSS/:focus-visible */ 75 | a:focus { 76 | /* Provide a fallback style for browsers 77 | that don't support :focus-visible */ 78 | outline: none; 79 | background: lightgrey; 80 | } 81 | 82 | a:focus:not(:focus-visible) { 83 | /* Remove the focus indicator on mouse-focus for browsers 84 | that do support :focus-visible */ 85 | background: transparent; 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 | background: transparent; 94 | } 95 | 96 | .unbutton { 97 | background: none; 98 | border: 0; 99 | padding: 0; 100 | margin: 0; 101 | font: inherit; 102 | cursor: pointer; 103 | } 104 | 105 | .unbutton:focus { 106 | outline: none; 107 | } 108 | 109 | .frame { 110 | z-index: 1000; 111 | position: fixed; 112 | width: 100%; 113 | padding: var(--padding-page); 114 | display: grid; 115 | grid-template-columns: 100%; 116 | grid-template-areas: 'title' 'prev' 'sponsor'; 117 | grid-gap: 0.5rem; 118 | justify-items: start; 119 | align-self: start; 120 | justify-self: start; 121 | pointer-events: none; 122 | align-items: center; 123 | } 124 | 125 | .loading .frame { 126 | opacity: 0; 127 | } 128 | 129 | body #cdawrap { 130 | justify-self: start; 131 | } 132 | 133 | .frame a { 134 | pointer-events: auto; 135 | } 136 | 137 | .frame a:not(.frame__title-back) { 138 | white-space: nowrap; 139 | overflow: hidden; 140 | position: relative; 141 | } 142 | 143 | .frame a:not(.frame__title-back)::before { 144 | content: ''; 145 | height: 1px; 146 | width: 100%; 147 | background: currentColor; 148 | position: absolute; 149 | top: 90%; 150 | transition: transform 0.3s; 151 | transform-origin: 0% 50%; 152 | } 153 | 154 | .frame a:not(.frame__title-back):hover::before { 155 | transform: scaleX(0); 156 | transform-origin: 100% 50%; 157 | } 158 | 159 | .frame__title { 160 | grid-area: title; 161 | display: flex; 162 | } 163 | 164 | .frame__title-main { 165 | font-size: inherit; 166 | margin: 0; 167 | font-weight: inherit; 168 | } 169 | 170 | .frame__title-back { 171 | position: relative; 172 | display: flex; 173 | align-items: flex-end; 174 | margin-bottom: 0.15rem; 175 | } 176 | 177 | .frame__title-back span { 178 | display: none; 179 | } 180 | 181 | .frame__title-back svg { 182 | fill: currentColor; 183 | } 184 | 185 | .frame__prev { 186 | grid-area: prev; 187 | } 188 | 189 | .deco { 190 | position: fixed; 191 | stroke: #fff; 192 | stroke-width: 1px; 193 | top: var(--padding-page); 194 | right: var(--padding-page); 195 | z-index: 900; 196 | pointer-events: none; 197 | fill: none; 198 | height: 150px; 199 | width: 150px; 200 | } 201 | 202 | .content { 203 | display: grid; 204 | grid-template-rows: 100vh 1fr auto; 205 | grid-template-columns: 100%; 206 | width: 100vw; 207 | --imgRatio: 1344 / 896; 208 | height: calc(var(--imgRatio) * 100vw); 209 | padding: 0 var(--padding-page); 210 | position: relative; 211 | } 212 | 213 | .canvas-wrap { 214 | position: absolute; 215 | top: 0; 216 | left: 0; 217 | height: 100%; 218 | width: 100%; 219 | background-position: 50% 50%; 220 | background-size: cover; 221 | opacity: 0; 222 | } 223 | 224 | .no-js .canvas-wrap { 225 | opacity: 1; 226 | } 227 | 228 | .content__inner { 229 | position: relative; 230 | justify-self: end; 231 | align-self: end; 232 | padding-bottom: var(--padding-page); 233 | } 234 | 235 | h2 { 236 | position: relative; 237 | font-size: 10vw; 238 | font-weight: 400; 239 | text-align: right; 240 | margin: 0; 241 | line-height: 0.8; 242 | } 243 | 244 | p { 245 | position: relative; 246 | grid-area: content; 247 | margin: 1rem 0 0 auto; 248 | text-align: right; 249 | max-width: 400px; 250 | justify-self: end; 251 | } 252 | 253 | h2 span:nth-child(even) { 254 | font-size: 10.5vw; 255 | font-family: "lores-9-plus-wide", sans-serif; 256 | } 257 | 258 | @media screen and (min-width: 53em) { 259 | .frame { 260 | height: 100vh; 261 | grid-template-columns: auto auto 1fr; 262 | grid-template-rows: auto auto; 263 | grid-template-areas: 'title prev ...' 'sponsor sponsor ...'; 264 | align-content: space-between; 265 | justify-items: start; 266 | grid-gap: 2rem; 267 | } 268 | .frame__demos { 269 | justify-self: end; 270 | } 271 | } 272 | -------------------------------------------------------------------------------- /favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/favicon.ico -------------------------------------------------------------------------------- /img/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/img/1.jpg -------------------------------------------------------------------------------- /img/2.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/img/2.jpg -------------------------------------------------------------------------------- /img/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/img/3.jpg -------------------------------------------------------------------------------- /img/4.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/img/4.jpg -------------------------------------------------------------------------------- /img/5.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/img/5.jpg -------------------------------------------------------------------------------- /img/6.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codrops/ImagePixelLoading/672443ebbb4f784150b15e40088b1bf96d110aac/img/6.jpg -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | On-Scroll Pixelated Image Loading Effect | Codrops 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 |

On-Scroll Pixelated Image Loading based on this

21 | 22 | Back to the article 23 | 24 | 25 | 26 |
27 | Previous demo 28 |
29 | 30 |
31 |
32 |
33 |

34 | DAAKO
35 | Nixie 36 |

37 |

Introducing the ethereal masterpiece, an epitome of sartorial splendor and avant-garde elegance. Behold, the breathtaking embodiment of haute couture opulence that transcends time and space. As your fingertips caress the luxurious fabric, a symphony of tactile delight unfolds, weaving dreams into reality.

38 |
39 |
40 |
41 |
42 |
43 |

44 | Rozen
45 | Novus 46 |

47 |

Draped in cascades of exquisite chiffon, this visionary creation embraces the essence of celestial allure. A celestial tapestry of celestial bodies unfolds, merging delicate sequins and celestial threads with celestial silk, encapsulating the whimsy of stardust captured in every stitch.

48 |
49 |
50 |
51 |
52 |
53 |

54 | Jadel
55 | Arden 56 |

57 |

The silhouette, a celestial dance between the divine and the divine, celebrates the human form, sculpting curves with an otherworldly grace. Each contour, meticulously tailored to accentuate the wearer's individuality, whispers tales of celestial grace and unspoken desires.

58 |
59 |
60 |
61 |
62 |
63 |

64 | Azura
65 | Exult 66 |

67 |

Emanating an aura of refined enchantment, the color palette transcends earthly confines. Radiant hues, reminiscent of an artist's palette, collide in harmonious symphony. From celestial blues that evoke the tranquil depths of the cosmic ocean to the celestial purples that mirror the twilight hues of distant galaxies, every shade resonates with the very essence of ethereal beauty.

68 |
69 |
70 |
71 |
72 |
73 |

74 | Quivo
75 | Folia 76 |

77 |

Merging haute couture craftsmanship with the spirit of celestial poetry, this divine creation is an ode to individuality and audacity. A testament to the symbiosis between imagination and technique, it beckons the wearer to embrace their inner divinity and embrace the celestial magnificence that resides within.

78 |
79 |
80 |
81 |
82 |
83 |

84 | Novus
85 | Oriel 86 |

87 |

Prepare to embark on a celestial journey of self-expression, where boundaries fade, and possibilities unfold. This haute couture masterpiece is a celestial hymn, an invitation to transcend the ordinary and embrace the extraordinary. Allow it to adorn your being, and experience the transcendence that only haute couture can bestow upon the soul.

88 |
89 |
90 |
91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /js/ScrollTrigger.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * ScrollTrigger 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(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(){(De=Me.core.globals().ScrollTrigger)&&De.core&&function _integrate(){var e=De.core,r=e.bridge||{},t=e._scrollers,n=e._proxies;t.push.apply(t,Ie),n.push.apply(n,qe),Ie=t,qe=n,i=function _bridge(e,t){return r[e](t)}}()}function P(e){return(Me=e||r())&&"undefined"!=typeof document&&document.body&&(ke=window,Pe=(Ee=document).documentElement,Oe=Ee.body,t=[ke,Ee,Pe,Oe],Me.utils.clamp,ze=Me.core.context||function(){},Be="onpointerenter"in Oe?"pointer":"mouse",Ae=k.isTouch=ke.matchMedia&&ke.matchMedia("(hover: none), (pointer: coarse)").matches?1:"ontouchstart"in ke||0=o,n=Math.abs(t)>=o;T&&(r||n)&&T(se,e,t,be,me),r&&(m&&0Math.abs(t)?"x":"y",ie=!0),"y"!==ae&&(be[2]+=e,se._vx.update(e,!0)),"x"!==ae&&(me[2]+=t,se._vy.update(t,!0)),n?ee=ee||requestAnimationFrame(Ve):Ve()}function Ye(e){if(!Te(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),Xe(n,o),i||d&&d(se))}}function _e(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 R?R[e]*t:~e.indexOf("%")?parseFloat(e)*t/100:parseFloat(e)||0)}return e}function wb(e,t,r,n,o,i,a,s){var l=o.startColor,c=o.endColor,u=o.fontSize,f=o.indent,p=o.fontWeight,d=Ge.createElement("div"),g=Fa(r)||"fixed"===z(r,"pinType"),h=-1!==e.indexOf("scroller"),v=g?Qe:r,b=-1!==e.indexOf("start"),m=b?l:c,y="border-color:"+m+";font-size:"+u+";color:"+m+";font-weight:"+p+";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===je?S:T)+":"+(i+parseFloat(f))+"px;"),a&&(y+="box-sizing:border-box;text-align:left;width:"+a.offsetWidth+"px;"),d._isStart=b,d.setAttribute("class","gsap-marker-"+e+(t?" marker-"+t:"")),d.style.cssText=y,d.innerText=t||0===t?e+"-"+t:e,v.children[0]?v.insertBefore(d,v.children[0]):v.appendChild(d),d._offset=d["offset"+n.op.d2],X(d,0,n,b),d}function Bb(){return 34Qe.clientWidth)||(Ie.cache++,v?w=w||requestAnimationFrame(W):W(),dt||q("scrollStart"),dt=pt())}function Db(){y=Ke.innerWidth,m=Ke.innerHeight}function Eb(){Ie.cache++,tt||h||Ge.fullscreenElement||Ge.webkitFullscreenElement||b&&y===Ke.innerWidth&&!(Math.abs(Ke.innerHeight-m)>.25*Ke.innerHeight)||c.restart(!0)}function Hb(){return qb($,"scrollEnd",Hb)||Bt(!0)}function Kb(e){for(var t=0;t=A})},Se.update=function(e,t,r){if(!pe||r||e){var n,o,i,a,s,l,c,u=!0===lt?Z:Se.scroll(),f=e?0:(u-O)/F,p=f<0?0:1=Ja(be,he),fe)if(e||!n&&!l)fc(ie,q);else{var g=Ct(ie,!0),h=u-O;fc(ie,Qe,g.top+(he===je?h:0)+Mt,g.left+(he===je?0:h)+Mt)}Rt(n||l?Y:I),j&&p<1&&n||b(V+(1!==p||l?0:H))}}else b(Ca(V+H*p));!ue||k.tween||tt||ft||U.restart(!0),ee&&(s||ce&&p&&(p<1||!st))&&Ze(ee.targets).forEach(function(e){return e.classList[n||ce?"add":"remove"](ee.className)}),!T||ve||e||T(Se),a&&!tt?(ve&&(c&&("complete"===i?C.pause().totalProgress(1):"reset"===i?C.restart(!0).pause():"restart"===i?C.restart(!0):C[i]()),T&&T(Se)),!s&&st||(te&&s&&Qa(Se,te),xe[o]&&Qa(Se,xe[o]),ce&&(1===p?Se.kill(!1,1):xe[o]=0),s||xe[o=1===p?1:3]&&Qa(Se,xe[o])),de&&!n&&Math.abs(Se.getVelocity())>(Na(de)?de:2500)&&(Pa(Se.callbackAnimation),G?G.progress(1):Pa(C,"reverse"===i?1:!p,1))):ve&&T&&!tt&&T(Se)}if(x){var v=pe?u/pe.duration()*(pe._caScrollDist||0):u;y(v+(R._isFlipped?1:0)),x(v)}S&&S(-u/pe.duration()*(pe._caScrollDist||0))}},Se.enable=function(e,t){Se.enabled||(Se.enabled=!0,pb(be,"resize",Eb),pb(me?Ge:be,"scroll",Cb),Te&&pb(ScrollTrigger,"refreshInit",Te),!1!==e&&(Se.progress=Q=0,E=P=ke=Pe()),!1!==t&&Se.refresh())},Se.getTween=function(e){return e&&k?k.tween:G},Se.setPositions=function(e,t){ie&&(V+=e-O,H+=t-e-F,ae===_t&&Se.adjustPinSpacing(t-e-F)),Se.start=O=e,Se.end=A=t,F=t-e,Se.update()},Se.adjustPinSpacing=function(e){if(W&&e){var t=W.indexOf(he.d)+1;W[t]=parseFloat(W[t])+e+Mt,W[1]=parseFloat(W[1])+e+Mt,Rt(W)}},Se.disable=function(e,t){if(Se.enabled&&(!1!==e&&Se.revert(!0,!0),Se.enabled=Se.isActive=!1,t||G&&G.pause(),Z=0,n&&(n.uncache=1),Te&&qb(ScrollTrigger,"refreshInit",Te),U&&(U.pause(),k.tween&&k.tween.kill()&&(k.tween=0)),!me)){for(var r=Pt.length;r--;)if(Pt[r].scroller===be&&Pt[r]!==Se)return;qb(be,"resize",Eb),qb(be,"scroll",Cb)}},Se.kill=function(e,t){Se.disable(e,t),G&&!t&&G.kill(),a&&delete Ot[a];var r=Pt.indexOf(Se);0<=r&&Pt.splice(r,1),r===nt&&0i&&(b()>i?a.progress(1)&&b(i):a.resetTo("scrollY",i))}Oa(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,p=e.onRelease,d=J(e.target)||Ue,g=Je.core.globals().ScrollSmoother,h=g&&g.get(),v=E&&(e.content&&J(e.content)||h&&!1!==e.content&&!h.smooth()&&h.content()),b=K(d,je),m=K(d,He),y=1,x=(k.isTouch&&Ke.visualViewport?Ke.visualViewport.scale*Ke.visualViewport.width:Ke.outerWidth)/Ke.innerWidth,w=0,_=Ma(t)?function(){return t(n)}:function(){return t||2.8},S=nc(d,e.type,!0,r),T=Ba,M=Ba;return v&&Je.set(v,{y:"+=0"}),e.ignoreCheck=function(e){return E&&"touchmove"===e.type&&function ignoreDrag(){if(o){requestAnimationFrame(Np);var e=Ca(n.deltaY/2),t=M(b.v-e);if(v&&t!==b.v+b.offset){b.offset=t-b.v;var r=Ca((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,W()}return!0}b.offset&&Rp(),o=!0}()||1.05=i||i-1<=r)&&Je.to({},{onUpdate:Xp,duration:o})}else s.restart(!0);p&&p(e)},e.onWheel=function(){a._ts&&a.pause(),1e3 { 54 | const imgWidth = this.img.width; 55 | const imgHeight = this.img.height; 56 | this.imgRatio = imgWidth / imgHeight; 57 | this.setCanvasSize(); 58 | this.render(); 59 | // Set up event listeners and triggers 60 | this.initEvents(); 61 | }; 62 | } 63 | 64 | /** 65 | * Sets up event listeners and the GSAP scroll triggers. 66 | * Handles resize events and triggers the pixelation 67 | * effect when the image enters the viewport. 68 | */ 69 | initEvents() { 70 | // Resize event handler 71 | window.addEventListener('resize', () => { 72 | this.setCanvasSize(); 73 | this.render(); 74 | }); 75 | 76 | // Trigger pixelation effect when reaching the 77 | // specific starting point: 78 | ScrollTrigger.create({ 79 | trigger: this.DOM.el, 80 | start: 'top+=20% bottom', 81 | onEnter: () => { 82 | this.animatePixels(); 83 | }, 84 | once: true 85 | }); 86 | 87 | // Add parallax effect to titles 88 | gsap.timeline({ 89 | scrollTrigger: { 90 | trigger: this.DOM.el, 91 | start: 'top bottom', 92 | end: 'bottom top', 93 | scrub: true 94 | } 95 | }) 96 | .to(this.DOM.inner, { 97 | ease: 'none', 98 | yPercent: -100 99 | }); 100 | 101 | // show canvasWrap when the element enters the viewport 102 | ScrollTrigger.create({ 103 | trigger: this.DOM.el, 104 | start: 'top bottom', 105 | onEnter: () => { 106 | gsap.set(this.DOM.canvasWrap, { 107 | opacity: 1 108 | }) 109 | }, 110 | once: true 111 | }); 112 | } 113 | 114 | /** 115 | * Sets the canvas size based on the dimensions 116 | * of the canvasWrap element. 117 | */ 118 | setCanvasSize() { 119 | this.DOM.canvas.width = this.DOM.canvasWrap.offsetWidth; 120 | this.DOM.canvas.height = this.DOM.canvasWrap.offsetHeight; 121 | } 122 | 123 | /** 124 | * Renders the image on the canvas. 125 | * Applies the pixelation effect based on the pixel factor. 126 | */ 127 | render() { 128 | const offsetWidth = this.DOM.canvasWrap.offsetWidth; 129 | const offsetHeight = this.DOM.canvasWrap.offsetHeight; 130 | // increase a bit to not have a gap in the end of the image 131 | // when we have big pizel sizes 132 | const w = offsetWidth + offsetWidth * 0.05; 133 | const h = offsetHeight + offsetHeight * 0.05; 134 | 135 | // Calculate the dimensions and position for rendering the image 136 | // within the canvas based on the image aspect ratio. 137 | let newWidth = w; 138 | let newHeight = h; 139 | let newX = 0; 140 | let newY = 0; 141 | 142 | // Adjust the dimensions and position if the image 143 | // aspect ratio is different from the canvas aspect ratio 144 | if (newWidth / newHeight > this.imgRatio) { 145 | newHeight = Math.round(w / this.imgRatio); 146 | // let's keep Y at 0 because we want the pixels to not 147 | // be cut off at the top. Uncomment if you want the 148 | // image to be centered. 149 | // newY = (h - newHeight) / 2; 150 | } else { 151 | newWidth = Math.round(h * this.imgRatio); 152 | newX = (w - newWidth) / 2; 153 | } 154 | 155 | // Get the pixel factor based on the current index 156 | let pxFactor = this.pxFactorValues[this.pxIndex]; 157 | const size = pxFactor * 0.01; 158 | 159 | // Turn off image smoothing to achieve the pixelated effect 160 | this.ctx.mozImageSmoothingEnabled = size === 1 ? true : false; 161 | this.ctx.webkitImageSmoothingEnabled = size === 1 ? true : false; 162 | this.ctx.imageSmoothingEnabled = size === 1 ? true : false; 163 | 164 | // Clear the canvas 165 | this.ctx.clearRect(0, 0, this.DOM.canvas.width, this.DOM.canvas.height); 166 | 167 | // Draw the original image at a fraction of the final size 168 | this.ctx.drawImage(this.img, 0, 0, w * size, h * size); 169 | 170 | // Enlarge the minimized image to full size 171 | this.ctx.drawImage( 172 | this.DOM.canvas, 173 | 0, 174 | 0, 175 | w * size, 176 | h * size, 177 | newX, 178 | newY, 179 | newWidth, 180 | newHeight 181 | ); 182 | } 183 | 184 | /** 185 | * Animates the pixelation effect. 186 | * Renders the image with increasing pixelation factor at each step. 187 | */ 188 | animatePixels() { 189 | if (this.pxIndex < this.pxFactorValues.length) { 190 | // Increase the pixelation factor and continue animating 191 | setTimeout(() => { 192 | // Render the image with the current pixelation factor 193 | this.render(); 194 | this.pxIndex++; 195 | this.animatePixels(); 196 | }, this.pxIndex === 0 ? 300 : 80); // The first time should be the longest. 197 | } 198 | else { 199 | this.pxIndex = this.pxFactorValues.length - 1; 200 | } 201 | } 202 | } 203 | -------------------------------------------------------------------------------- /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/index.js: -------------------------------------------------------------------------------- 1 | import { preloadImages } from './utils.js'; 2 | import { Content } from './content.js'; 3 | 4 | // Smooth scrolling. 5 | let lenis; 6 | const initSmoothScrolling = () => { 7 | // Smooth scrolling initialization (using Lenis https://github.com/studio-freight/lenis) 8 | lenis = new Lenis({ 9 | lerp: 0.1, 10 | smoothWheel: true, 11 | orientation: 'vertical', 12 | }); 13 | 14 | lenis.on('scroll', () => ScrollTrigger.update()); 15 | 16 | const scrollFn = () => { 17 | lenis.raf(); 18 | requestAnimationFrame(scrollFn); 19 | }; 20 | requestAnimationFrame(scrollFn); 21 | }; 22 | 23 | // .content elements 24 | const contentElems = [...document.querySelectorAll('.content')]; 25 | contentElems.forEach(el => new Content(el)); 26 | 27 | // smooth scrolling with Lenis 28 | initSmoothScrolling(); 29 | 30 | // Preload images then remove loader (loading class) from body 31 | preloadImages('.canvas-wrap').then(() => document.body.classList.remove('loading')); -------------------------------------------------------------------------------- /js/lenis.min.js: -------------------------------------------------------------------------------- 1 | !function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t||self).Lenis=e()}(this,function(){function t(t,e){for(var i=0;i=1)?1:this.easing(s);this.value=this.from+(this.to-this.from)*r}null==(e=this.onUpdate)||e.call(this,this.value,{completed:n}),n&&this.stop()}},e.stop=function(){this.isRunning=!1},e.fromTo=function(t,e,i){var o=i.lerp,n=void 0===o?.1:o,s=i.duration,r=void 0===s?1:s,l=i.easing,h=void 0===l?function(t){return t}:l,a=i.onUpdate;this.from=this.value=t,this.to=e,this.lerp=n,this.duration=r,this.easing=h,this.currentTime=0,this.isRunning=!0,this.onUpdate=a},t}();function s(t,e){var i;return function(){var o=arguments,n=this;clearTimeout(i),i=setTimeout(function(){t.apply(n,o)},e)}}var r=/*#__PURE__*/function(){function t(t,e){var i=this;this.onWindowResize=function(){i.width=window.innerWidth,i.height=window.innerHeight},this.onWrapperResize=function(){i.width=i.wrapper.clientWidth,i.height=i.wrapper.clientHeight},this.onContentResize=function(){var t=i.wrapper===window?document.documentElement:i.wrapper;i.scrollHeight=t.scrollHeight,i.scrollWidth=t.scrollWidth},this.wrapper=t,this.content=e,this.wrapper===window?(window.addEventListener("resize",this.onWindowResize,!1),this.onWindowResize()):(this.wrapperResizeObserver=new ResizeObserver(s(this.onWrapperResize,100)),this.wrapperResizeObserver.observe(this.wrapper),this.onWrapperResize()),this.contentResizeObserver=new ResizeObserver(s(this.onContentResize,100)),this.contentResizeObserver.observe(this.content),this.onContentResize()}return t.prototype.destroy=function(){var t,e;window.removeEventListener("resize",this.onWindowResize,!1),null==(t=this.wrapperResizeObserver)||t.disconnect(),null==(e=this.contentResizeObserver)||e.disconnect()},e(t,[{key:"limit",get:function(){return{x:this.scrollWidth-this.width,y:this.scrollHeight-this.height}}}]),t}(),l=/*#__PURE__*/function(){function t(t,e){var i=this,n=e.wheelMultiplier,s=void 0===n?1:n,r=e.touchMultiplier,l=void 0===r?2:r,h=e.normalizeWheel,a=void 0!==h&&h;this.onTouchStart=function(t){var e=t.targetTouches?t.targetTouches[0]:t,o=e.clientY;i.touchStart.x=e.clientX,i.touchStart.y=o,i.lastDelta={x:0,y:0}},this.onTouchMove=function(t){var e=t.targetTouches?t.targetTouches[0]:t,o=e.clientX,n=e.clientY,s=-(o-i.touchStart.x)*i.touchMultiplier,r=-(n-i.touchStart.y)*i.touchMultiplier;i.touchStart.x=o,i.touchStart.y=n,i.lastDelta={x:s,y:r},i.emitter.emit("scroll",{type:"touch",deltaX:s,deltaY:r,event:t})},this.onTouchEnd=function(t){i.emitter.emit("scroll",{type:"touch",inertia:!0,deltaX:i.lastDelta.x,deltaY:i.lastDelta.y,event:t})},this.onWheel=function(t){var e=t.deltaX,n=t.deltaY;i.normalizeWheel&&(e=o(-100,e,100),n=o(-100,n,100)),i.emitter.emit("scroll",{type:"wheel",deltaX:e*=i.wheelMultiplier,deltaY:n*=i.wheelMultiplier,event:t})},this.element=t,this.wheelMultiplier=s,this.touchMultiplier=l,this.normalizeWheel=a,this.touchStart={x:null,y:null},this.emitter={events:{},emit:function(t){for(var e=this.events[t]||[],i=0,o=e.length;iMath.abs(s)?r:s:"horizontal"===e.options.gestureOrientation&&(c=s);var u=h&&e.options.syncTouch,p=h&&n&&Math.abs(c)>1;p&&(c=e.velocity*e.options.touchInertiaMultiplier),e.scrollTo(e.targetScroll+c,i({programmatic:!1},u&&{lerp:p?e.syncTouchLerp:.4}))}}},this.onScroll=function(){if(!e.isScrolling){var t=e.animatedScroll;e.animatedScroll=e.targetScroll=e.actualScroll,e.velocity=0,e.direction=Math.sign(e.animatedScroll-t),e.emit()}},s&&console.warn("Lenis: `direction` option is deprecated, use `orientation` instead"),h&&console.warn("Lenis: `gestureDirection` option is deprecated, use `gestureOrientation` instead"),a&&console.warn("Lenis: `mouseMultiplier` option is deprecated, use `wheelMultiplier` instead"),c&&console.warn("Lenis: `smooth` option is deprecated, use `smoothWheel` instead"),window.lenisVersion="1.0.11",p!==document.documentElement&&p!==document.body||(p=window),this.options={wrapper:p,content:v,wheelEventsTarget:f,smoothWheel:w,smoothTouch:y,syncTouch:b,syncTouchLerp:M,touchInertiaMultiplier:L,duration:W,easing:O,lerp:k,infinite:H,gestureOrientation:Y,orientation:D,touchMultiplier:P,wheelMultiplier:A,normalizeWheel:V},this.dimensions=new r(p,v),this.rootElement.classList.add("lenis"),this.velocity=0,this.isStopped=!1,this.isSmooth=w||y,this.isScrolling=!1,this.targetScroll=this.animatedScroll=this.actualScroll,this.animate=new n,this.emitter={events:{},emit:function(t){for(var e=this.events[t]||[],i=0,o=e.length;i0&&e<0||t<0&&e>0)&&(e+=t),e):this.animatedScroll;var t,e}},{key:"progress",get:function(){return 0===this.limit?1:this.scroll/this.limit}},{key:"isSmooth",get:function(){return this.__isSmooth},set:function(t){this.__isSmooth!==t&&(this.rootElement.classList.toggle("lenis-smooth",t),this.__isSmooth=t)}},{key:"isScrolling",get:function(){return this.__isScrolling},set:function(t){this.__isScrolling!==t&&(this.rootElement.classList.toggle("lenis-scrolling",t),this.__isScrolling=t)}},{key:"isStopped",get:function(){return this.__isStopped},set:function(t){this.__isStopped!==t&&(this.rootElement.classList.toggle("lenis-stopped",t),this.__isStopped=t)}}]),t}();return h}); -------------------------------------------------------------------------------- /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 | }; --------------------------------------------------------------------------------