2. Counter Animation
Numbers automatically animate when they enter the viewport.
Required Structure
<div class="counter" data-target="125">
0
</div>
3. Smooth Scrolling (Lenis)
Smooth scrolling is automatically enabled on desktop devices only.
if (!window.matchMedia("(min-width: 768px)").matches) return;
Change Scroll Speed
const lenis = new Lenis({
duration: 0.9
});
4. Image Overly Animaiton
Smooth scrolling is automatically enabled on desktop devices only.
{
const D = 90,
IN = 0.2,
MOVE = 0.45,
OUT = 0.2,
SCALE = 0.6;
const waitForLoad = (cb) => {
const fn = () => {
if (document.readyState === "complete") {
gsap.ticker.remove(fn);
cb();
}
};
gsap.ticker.add(fn);
};
waitForLoad(() => {
const hero = document.querySelector(".about");
const wrap = hero && hero.querySelector(".image_wrap");
const items = wrap
? gsap.utils.toArray(".content_img-wrap", wrap)
: [];
if (!hero || !wrap || !items.length) return;
gsap.set(wrap, {
position: "relative",
overflow: "visible"
});
gsap.set(items, {
position: "absolute",
willChange: "transform,opacity"
});
let rect = wrap.getBoundingClientRect();
let over = false,
first = true,
i = -1,
z = 1;
let last = { x: 0, y: 0 };
let curr = { x: 0, y: 0 };
const refreshRect = () => {
if (over) rect = wrap.getBoundingClientRect();
};
gsap.ticker.add(refreshRect);
const toLocal = (e) => ({
x: e.clientX - rect.left,
y: e.clientY - rect.top
});
function spawn(fromX, fromY, toX, toY) {
i = (i + 1) % items.length;
const el = items[i];
const img = el.querySelector(".content_img") || el;
gsap.set(el, {
left: 0,
top: 0,
zIndex: ++z
});
gsap.set(img, {
opacity: 1,
scale: 1
});