Files
citrus/resources/views/templates/neler-yapariz/js/hero.js
T

263 lines
5.8 KiB
JavaScript

{
const split = (text, type = "chars") => {
// Handle both single elements and arrays of elements
const elements = Array.isArray(text) ? text : [text];
// Set aria labels
elements.forEach((element) => {
if (element && typeof element.setAttribute === "function") {
element.setAttribute("aria-label", element.textContent);
}
});
// Split text and set aria-hidden
const splits = new SplitText(text, { type });
splits[type].forEach((char) => {
if (char && typeof char.setAttribute === "function") {
char.setAttribute("aria-hidden", "true");
}
});
return splits[type];
};
/** -- Setup and Utils */
let titleSplit,
parSplit,
layerItems,
isIn = false;
const animateIn = async (delay = 0) => {
isIn = true;
animateStripesOut();
gsap.to(parSplit, {
autoAlpha: 1,
yPercent: 0,
duration: 0.8,
delay: 0.65,
ease: "expo.out",
stagger: {
each: 0.08,
},
});
await gsap.to(titleSplit.flat(), {
yPercent: 0,
duration: 1.2,
delay: delay,
ease: "expo.out",
stagger: {
each: 0.01,
from: "end",
},
});
};
const animateOut = async () => {
isIn = false;
animateStripesIn();
gsap.to(parSplit, {
autoAlpha: 0,
yPercent: 100,
duration: 0.8,
ease: "expo.out",
stagger: {
each: 0.08,
},
});
await gsap.to(titleSplit.flat(), {
yPercent: 110,
duration: 0.8,
ease: "expo.out",
delay: 0.1,
stagger: {
each: 0.01,
from: "center",
},
});
};
/** -- Scribble Animaiton */
let isScribbling = false;
const SCRIBBLE_CONFIG = {
ROTATION_RANGE: 20,
TIME_BETWEEN_SCRIBBLES: 0.015,
VISIBILITY_DURATION: 0.01,
REVERSE_ORDER: true,
};
const animateScribble = (scribble) => {
if (isScribbling) return;
isScribbling = true;
gsap.set(scribble, { autoAlpha: 0, rotation: 0 });
const tl = gsap.timeline();
const scribblesToAnimate = [...scribble].reverse();
scribblesToAnimate.forEach((item, index) => {
const randomRotation =
Math.random() * SCRIBBLE_CONFIG.ROTATION_RANGE -
SCRIBBLE_CONFIG.ROTATION_RANGE / 2;
const baseDelay = index * SCRIBBLE_CONFIG.TIME_BETWEEN_SCRIBBLES;
tl.add(
gsap.set(item, {
autoAlpha: 1,
rotation: randomRotation,
delay: baseDelay,
})
);
tl.add(
gsap.set(item, {
autoAlpha: 0,
delay: baseDelay + SCRIBBLE_CONFIG.VISIBILITY_DURATION,
})
);
});
tl.call(() => {
isScribbling = false;
});
};
// hero stripes animation
let heroStripes,
stripes,
stripesAnimation = null;
const calcX = (i) => {
return i % 2 === 0
? -heroStripes[i].scrollWidth
: heroStripes[i].scrollWidth;
};
const animateStripesIn = () => {
if (stripesAnimation) {
stripesAnimation.kill();
}
// play video on the hero
document.querySelector("video").play()
gsap.set(heroStripes, {
autoAlpha: 1,
x: (i) => calcX(i),
yPercent: (i) => (heroStripes.length / 2 - i) * 80,
});
gsap.set(stripes, {
rotation: (i) => Math.random() * 30,
ease: "expo.out",
});
stripesAnimation = gsap.to(heroStripes, {
x: 0,
delay: 0.2,
duration: (i) => Math.random() + 1.2,
ease: "expo.out",
});
};
const animateStripesOut = () => {
if (stripesAnimation) {
stripesAnimation.kill();
}
stripesAnimation = gsap.to(heroStripes, {
x: (i) => calcX(i),
duration: 0.8,
ease: "expo.out",
});
};
addEventListener("GSAPReady", (event) => {
const wrapper = document.querySelector("[data-module='hero']");
if (!wrapper) return;
const layer = wrapper.querySelector("[data-hero='layer']");
layerItems = layer.children;
const title = wrapper.querySelector("[data-hero='title']");
const toggle = wrapper.querySelector("[data-hero='toggle']");
const alpha = document.querySelectorAll("[data-hero='alpha']");
const par = document.querySelectorAll("[data-hero='par']");
const scribble = [
...document.querySelector("[data-hero='scribble']").children[0].children,
];
stripes = [...layer.children];
heroStripes = stripes.map((item) => item.children[0]);
gsap.set(heroStripes, { autoAlpha: 0 });
gsap.to(layer, {
yPercent: 10,
scrollTrigger: {
trigger: layer,
start: "top top",
end: "+=100%",
scrub: true,
},
});
// split
titleSplit = split(title.children, "chars");
parSplit = split(par, "lines");
// initial state
gsap.set(titleSplit.flat(), { yPercent: -110 });
gsap.set(layer, { autoAlpha: 1 });
gsap.set(toggle, { scale: 3, rotation: 360 });
gsap.set(parSplit, { autoAlpha: 0, yPercent: 100 });
gsap.set(alpha, { autoAlpha: 0, scale: 0.7 });
gsap.set(scribble, { autoAlpha: 0 });
animateIn(0.6);
gsap.to(toggle, {
scale: 1,
rotation: 0,
delay: 0,
duration: 1.2,
ease: "expo.inOut",
});
gsap.to(parSplit, {
autoAlpha: 1,
yPercent: 0,
duration: 0.8,
delay: 0.65,
ease: "expo.out",
stagger: {
each: 0.08,
},
});
gsap.to(alpha, {
autoAlpha: 1,
scale: 1,
duration: 0.8,
delay: 0.9,
ease: "expo.out",
});
toggle.querySelector("input").addEventListener("change", (event) => {
if (event.target.checked) {
animateOut();
} else {
animateIn();
}
});
toggle.onmouseenter = () => {
if (!isIn) return;
// console.log("mouseenter");
animateScribble(scribble);
};
});
}