Files
aritmija/aritmija_devTemplate/v3/assets/js/main.js
2026-05-13 17:11:09 +02:00

1555 lines
34 KiB
JavaScript

// ===== Team Slider: Infinite + Smooth Momentum Drag =====
gsap.registerPlugin(Draggable);
const teamTrack = document.querySelector(".team-track");
if (teamTrack) {
if (!teamTrack.dataset.cloned) {
teamTrack.innerHTML += teamTrack.innerHTML;
teamTrack.dataset.cloned = "true";
}
const totalWidth = teamTrack.scrollWidth / 2;
const wrapX = gsap.utils.wrap(-totalWidth, 0);
gsap.set(teamTrack, { x: 0 });
const loopTween = gsap.to(teamTrack, {
x: -totalWidth,
duration: 100,
ease: "none",
repeat: -1,
modifiers: {
x: x => `${wrapX(parseFloat(x))}px`
}
});
const proxy = document.createElement("div");
let currentX = 0;
let lastX = 0;
let velocity = 0;
let momentumTween = null;
function getTrackX() {
return wrapX(gsap.getProperty(teamTrack, "x"));
}
function setTrackX(x) {
currentX = wrapX(x);
gsap.set(teamTrack, { x: currentX });
const progress = Math.abs(currentX / totalWidth);
loopTween.progress(progress);
}
function resumeLoop() {
loopTween.play();
gsap.fromTo(
loopTween,
{ timeScale: 0 },
{
timeScale: 1,
duration: 1,
ease: "power3.out"
}
);
}
Draggable.create(proxy, {
type: "x",
trigger: teamTrack,
dragResistance: 0.08,
minimumMovement: 12,
allowNativeTouchScrolling: true,
onPress(e) {
this.startPointerX = e.clientX || e.touches?.[0]?.clientX || 0;
this.startPointerY = e.clientY || e.touches?.[0]?.clientY || 0;
this.isHorizontalDrag = false;
if (momentumTween) momentumTween.kill();
currentX = getTrackX();
lastX = currentX;
velocity = 0;
gsap.set(proxy, { x: currentX });
teamTrack.style.cursor = "grabbing";
},
onDrag(e) {
const pointerX = e.clientX || e.touches?.[0]?.clientX || this.pointerX || 0;
const pointerY = e.clientY || e.touches?.[0]?.clientY || this.pointerY || 0;
const diffX = Math.abs(pointerX - this.startPointerX);
const diffY = Math.abs(pointerY - this.startPointerY);
if (!this.isHorizontalDrag) {
if (diffY > diffX) return;
if (diffX > 12 && diffX > diffY) {
this.isHorizontalDrag = true;
loopTween.pause();
}
}
if (!this.isHorizontalDrag) return;
const x = gsap.getProperty(proxy, "x");
velocity = x - lastX;
lastX = x;
setTrackX(x);
},
onRelease() {
teamTrack.style.cursor = "grab";
if (!this.isHorizontalDrag) {
resumeLoop();
return;
}
const startX = gsap.getProperty(proxy, "x");
const throwDistance = velocity * 10;
momentumTween = gsap.to(proxy, {
x: startX + throwDistance,
duration: 0.75,
ease: "power2.out",
onUpdate() {
setTrackX(gsap.getProperty(proxy, "x"));
},
onComplete() {
resumeLoop();
}
});
}
});
teamTrack.style.cursor = "grab";
teamTrack.addEventListener("mouseenter", () => {
gsap.to(loopTween, {
timeScale: 0.2,
duration: 0.3,
ease: "power3.out"
});
});
teamTrack.addEventListener("mouseleave", () => {
gsap.to(loopTween, {
timeScale: 1,
duration: 0.4,
ease: "power3.out"
});
});
}
// ===== Inspiration Timeline Slider =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined" || typeof Draggable === "undefined") return;
const slider = document.querySelector(".inspiration-overlay-slider");
const wrap = document.querySelector(".slider-wrapper");
if (!slider || !wrap) return;
const cards = Array.from(slider.children);
cards.forEach((card) => {
slider.appendChild(card.cloneNode(true));
});
const totalWidth = slider.scrollWidth / 2;
const wrapX = gsap.utils.wrap(-totalWidth, 0);
gsap.set(slider, { x: 0 });
const tween = gsap.to(slider, {
x: -totalWidth,
duration: 160,
ease: "none",
repeat: -1,
modifiers: {
x: (x) => `${wrapX(parseFloat(x))}px`
}
});
const proxy = document.createElement("div");
let currentX = 0;
let lastX = 0;
let velocity = 0;
let momentumTween = null;
function getSliderX() {
return wrapX(gsap.getProperty(slider, "x"));
}
function setSliderX(x) {
currentX = wrapX(x);
gsap.set(slider, {
x: currentX
});
const progress = Math.abs(currentX / totalWidth);
tween.progress(progress);
}
function resumeLoop() {
tween.play();
gsap.fromTo(
tween,
{ timeScale: 0 },
{
timeScale: 1,
duration: 1,
ease: "power3.out"
}
);
}
Draggable.create(proxy, {
type: "x",
trigger: slider,
dragResistance: 0.08,
minimumMovement: 10,
allowNativeTouchScrolling: true,
onPress(e) {
this.startPointerX = e.clientX || e.touches?.[0]?.clientX || 0;
this.startPointerY = e.clientY || e.touches?.[0]?.clientY || 0;
this.isHorizontalDrag = false;
if (momentumTween) momentumTween.kill();
tween.pause();
currentX = getSliderX();
lastX = currentX;
velocity = 0;
gsap.set(proxy, {
x: currentX
});
wrap.classList.add("is-dragging");
},
onDrag(e) {
const pointerX = e.clientX || e.touches?.[0]?.clientX || this.pointerX || 0;
const pointerY = e.clientY || e.touches?.[0]?.clientY || this.pointerY || 0;
const diffX = Math.abs(pointerX - this.startPointerX);
const diffY = Math.abs(pointerY - this.startPointerY);
if (!this.isHorizontalDrag) {
if (diffY > diffX) return;
if (diffX > 10 && diffX > diffY) {
this.isHorizontalDrag = true;
}
}
if (!this.isHorizontalDrag) return;
const x = gsap.getProperty(proxy, "x");
velocity = x - lastX;
lastX = x;
setSliderX(x);
},
onRelease() {
wrap.classList.remove("is-dragging");
if (!this.isHorizontalDrag) {
resumeLoop();
return;
}
const startX = gsap.getProperty(proxy, "x");
const throwDistance = velocity * 10;
momentumTween = gsap.to(proxy, {
x: startX + throwDistance,
duration: 0.75,
ease: "power2.out",
onUpdate() {
setSliderX(gsap.getProperty(proxy, "x"));
},
onComplete() {
resumeLoop();
}
});
}
});
wrap.addEventListener("mouseenter", () => {
gsap.to(tween, {
timeScale: 0.2,
duration: 0.4,
ease: "power3.out"
});
});
wrap.addEventListener("mouseleave", () => {
gsap.to(tween, {
timeScale: 1,
duration: 0.5,
ease: "power3.out"
});
});
});
// ===== Portfolio Slider: Infinite + Smooth Momentum Drag =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined" || typeof Draggable === "undefined") return;
const slider = document.querySelector(".portfolio-slider");
const wrap = document.querySelector(".portfolio-slider-wrap");
if (!slider || !wrap) return;
const originalSlides = Array.from(slider.children);
originalSlides.forEach((slide) => {
slider.appendChild(slide.cloneNode(true));
});
const totalWidth = slider.scrollWidth / 2;
const wrapX = gsap.utils.wrap(-totalWidth, 0);
gsap.set(slider, { x: 0 });
const loopTween = gsap.to(slider, {
x: -totalWidth,
duration: 55,
ease: "none",
repeat: -1,
modifiers: {
x: (x) => `${wrapX(parseFloat(x))}px`
}
});
const proxy = document.createElement("div");
let currentX = 0;
let lastX = 0;
let velocity = 0;
let momentumTween = null;
function getSliderX() {
return wrapX(gsap.getProperty(slider, "x"));
}
function setSliderX(x) {
currentX = wrapX(x);
gsap.set(slider, {
x: currentX
});
const progress = Math.abs(currentX / totalWidth);
loopTween.progress(progress);
}
function resumeLoop() {
loopTween.play();
gsap.fromTo(
loopTween,
{
timeScale: 0
},
{
timeScale: 1,
duration: 1.2,
ease: "power3.out"
}
);
}
Draggable.create(proxy, {
type: "x",
trigger: wrap,
dragResistance: 0.08,
minimumMovement: 12,
allowNativeTouchScrolling: true,
onPress(e) {
this.startPointerX = e.clientX || e.touches?.[0]?.clientX || 0;
this.startPointerY = e.clientY || e.touches?.[0]?.clientY || 0;
this.isHorizontalDrag = false;
if (momentumTween) momentumTween.kill();
loopTween.pause();
currentX = getSliderX();
lastX = currentX;
velocity = 0;
gsap.set(proxy, {
x: currentX
});
},
onDrag(e) {
const pointerX = e.clientX || e.touches?.[0]?.clientX || this.pointerX || 0;
const pointerY = e.clientY || e.touches?.[0]?.clientY || this.pointerY || 0;
const diffX = Math.abs(pointerX - this.startPointerX);
const diffY = Math.abs(pointerY - this.startPointerY);
if (!this.isHorizontalDrag) {
if (diffY > diffX) {
return;
}
if (diffX > 12 && diffX > diffY) {
this.isHorizontalDrag = true;
wrap.classList.add("is-dragging");
}
}
if (!this.isHorizontalDrag) return;
const x = gsap.getProperty(proxy, "x");
velocity = x - lastX;
lastX = x;
setSliderX(x);
},
onRelease() {
wrap.classList.remove("is-dragging");
if (!this.isHorizontalDrag) {
resumeLoop();
return;
}
const startX = gsap.getProperty(proxy, "x");
const throwDistance = velocity * 12;
momentumTween = gsap.to(proxy, {
x: startX + throwDistance,
duration: 0.8,
ease: "power2.out",
onUpdate() {
setSliderX(gsap.getProperty(proxy, "x"));
},
onComplete() {
resumeLoop();
}
});
}
});
wrap.addEventListener("mouseenter", () => {
gsap.to(loopTween, {
timeScale: 0.25,
duration: 0.45,
ease: "power3.out"
});
});
wrap.addEventListener("mouseleave", () => {
gsap.to(loopTween, {
timeScale: 1,
duration: 0.65,
ease: "power3.out"
});
});
});
// ===== Mobile Services Slow Story Scroll =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined" || typeof ScrollTrigger === "undefined") return;
if (window.innerWidth > 767) return;
const wrapper = document.querySelector(".services-story-mobile-wrap");
const section = document.querySelector(".services-word-cloud");
const serviceWords = gsap.utils.toArray(".service-word");
if (!wrapper || !section || !serviceWords.length) return;
let preview = document.querySelector(".mobile-service-preview");
if (preview) {
document.body.appendChild(preview);
}
const scrollDistance = serviceWords.length * 180;
function setActive(index) {
serviceWords.forEach((word, i) => {
word.classList.toggle("is-active", i === index);
});
const img = serviceWords[index].querySelector("img");
if (img && preview) {
preview.src = img.getAttribute("src");
preview.classList.add("is-visible");
}
}
ScrollTrigger.create({
trigger: wrapper,
start: "top 20%",
end: "+=" + scrollDistance,
pin: section,
pinSpacing: true,
scrub: true,
anticipatePin: 1,
invalidateOnRefresh: true,
// first activation only when pinned
onEnter: () => {
setActive(0);
},
onEnterBack: () => {
setActive(0);
},
onUpdate: (self) => {
const index = Math.min(
serviceWords.length - 1,
Math.floor(self.progress * serviceWords.length)
);
setActive(index);
},
onLeave: () => {
if (preview) {
preview.classList.remove("is-visible");
}
serviceWords.forEach((word) => {
word.classList.remove("is-active");
});
},
onLeaveBack: () => {
if (preview) {
preview.classList.remove("is-visible");
}
serviceWords.forEach((word) => {
word.classList.remove("is-active");
});
}
});
ScrollTrigger.refresh();
});
// ===== Hero Video Scale On Scroll =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined" || typeof ScrollTrigger === "undefined") return;
gsap.fromTo(".hero-video",
{
width: "70%",
height: "75vh"
},
{
width: "100%",
height: "100vh",
ease: "none",
scrollTrigger: {
trigger: ".hero-area",
start: "top 130%",
end: "top top",
scrub: 1
}
}
);
});
// ===== Awards Cursor Image Trail =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined") return;
const section = document.querySelector(".about-area2");
if (!section) return;
const flair = gsap.utils.toArray(".about-area2 .flair");
if (!flair.length) return;
let gap = 100;
let index = 0;
let wrapper = gsap.utils.wrap(0, flair.length);
let mousePos = { x: 0, y: 0 };
let lastMousePos = { x: 0, y: 0 };
let isInside = false;
let idleTimeout;
function playAnimation(shape) {
gsap.timeline()
.from(shape, {
opacity: 0,
scale: 0,
ease: "elastic.out(1,0.3)",
duration: 0.35
})
.to(shape, {
rotation: "random([-360,360])"
}, "<")
.to(shape, {
y: section.offsetHeight + 200,
opacity: 0,
ease: "power2.in",
duration: 1.4
}, 0);
}
function hideAllFlair() {
gsap.to(flair, {
opacity: 0,
duration: 0.25,
overwrite: true
});
}
section.addEventListener("mouseenter", function (e) {
isInside = true;
const rect = section.getBoundingClientRect();
mousePos = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
lastMousePos = { ...mousePos };
});
section.addEventListener("mouseleave", function () {
isInside = false;
clearTimeout(idleTimeout);
hideAllFlair();
});
section.addEventListener("mousemove", function (e) {
clearTimeout(idleTimeout);
const rect = section.getBoundingClientRect();
mousePos = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
};
idleTimeout = setTimeout(() => {
hideAllFlair();
}, 180);
});
gsap.ticker.add(function () {
if (!isInside) return;
let travelDistance = Math.hypot(
lastMousePos.x - mousePos.x,
lastMousePos.y - mousePos.y
);
if (travelDistance > gap) {
let wrappedIndex = wrapper(index);
let img = flair[wrappedIndex];
gsap.killTweensOf(img);
gsap.set(img, {
clearProps: "all"
});
gsap.set(img, {
opacity: 1,
left: mousePos.x,
top: mousePos.y,
xPercent: -50,
yPercent: -50
});
playAnimation(img);
lastMousePos = { ...mousePos };
index++;
}
});
});
// ===== Brand Dock Infinite Scroll + Mac Dock Effect =====
const dock = document.querySelector(".brand-dock");
if (dock && typeof gsap !== "undefined") {
const originalItems = Array.from(dock.children);
for (let i = 0; i < 4; i++) {
originalItems.forEach(item => {
dock.appendChild(item.cloneNode(true));
});
}
const totalWidth = dock.scrollWidth / 5;
const wrapX = gsap.utils.wrap(-totalWidth, 0);
gsap.set(dock, { x: 0 });
gsap.to(dock, {
x: -totalWidth,
duration: 39.2,
ease: "none",
repeat: -1,
modifiers: {
x: x => `${wrapX(parseFloat(x))}px`
}
});
const allLogos = dock.querySelectorAll(".brand-dock-img");
dock.addEventListener("mousemove", (event) => {
allLogos.forEach((logo) => {
const rect = logo.getBoundingClientRect();
const center = rect.left + rect.width / 2;
const distance = Math.abs(event.clientX - center);
const maxDistance = 260;
const minScale = 1;
const maxScale = 1.45;
const proximity = Math.max(0, 1 - distance / maxDistance);
const scale = minScale + proximity * (maxScale - minScale);
gsap.to(logo, {
scale: scale,
duration: 0.32,
ease: "power3.out",
overwrite: true
});
});
});
dock.addEventListener("mouseleave", () => {
gsap.to(allLogos, {
scale: 1,
duration: 0.4,
ease: "power3.out",
overwrite: true
});
});
}
// ===== Multiple H2 Word by Word Scroll Reveal =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined" || typeof ScrollTrigger === "undefined") return;
const blocks = document.querySelectorAll(
".together-content h2, .together-content2 h2"
);
blocks.forEach((block) => {
const words = block.textContent.trim().split(" ");
block.innerHTML = words
.map(word => `<span class="word-reveal-word">${word} </span>`)
.join("");
const spans = block.querySelectorAll(".word-reveal-word");
gsap.to(spans, {
color: "#4050FF",
stagger: 0.08,
ease: "power2.out",
scrollTrigger: {
trigger: block,
start: "top 105%",
end: "bottom 45%",
scrub: 1.2
}
});
});
});
// ===== Page Reveal =====
document.addEventListener("DOMContentLoaded", function () {
const reveal = document.querySelector(".page-reveal");
const header = document.querySelector(".header");
if (!reveal || typeof gsap === "undefined") return;
const headerHeight = header ? header.offsetHeight : 0;
gsap.set(reveal, {
top: headerHeight,
scaleY: 1,
transformOrigin: "top center"
});
gsap.to(reveal, {
scaleY: 0,
duration: 1.5,
ease: "expo.inOut",
delay: 0.1,
onComplete() {
reveal.remove();
}
});
});
// ===== Global Smooth Scroll / Lenis =====
document.addEventListener("DOMContentLoaded", function () {
if (typeof Lenis === "undefined") return;
const lenis = new Lenis({
duration: 1.2,
smoothWheel: true,
smoothTouch: true,
touchMultiplier: 1.15,
wheelMultiplier: 1,
lerp: 0.08
});
function raf(time) {
lenis.raf(time);
requestAnimationFrame(raf);
}
requestAnimationFrame(raf);
if (typeof ScrollTrigger !== "undefined") {
lenis.on("scroll", ScrollTrigger.update);
}
});
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined") return;
const awardContainer = document.querySelector(".award-container");
const awardsWrap = document.querySelector(".awards-wrap");
const awards = document.querySelectorAll(".awards-wrap img");
if (!awardContainer || !awardsWrap || !awards.length) return;
gsap.set(awardContainer, {
perspective: 1400
});
gsap.set(awardsWrap, {
transformStyle: "preserve-3d"
});
gsap.set(awards, {
transformStyle: "preserve-3d"
});
const wrapRotateX = gsap.quickTo(awardsWrap, "rotationX", {
duration: 0.45,
ease: "power2.out"
});
const wrapRotateY = gsap.quickTo(awardsWrap, "rotationY", {
duration: 0.45,
ease: "power2.out"
});
const wrapX = gsap.quickTo(awardsWrap, "x", {
duration: 0.45,
ease: "power2.out"
});
const wrapY = gsap.quickTo(awardsWrap, "y", {
duration: 0.45,
ease: "power2.out"
});
awardContainer.addEventListener("pointermove", function (e) {
const rect = awardContainer.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
const rotateY = gsap.utils.interpolate(-16, 16, x);
const rotateX = gsap.utils.interpolate(12, -12, y);
const moveX = gsap.utils.interpolate(-28, 28, x);
const moveY = gsap.utils.interpolate(-22, 22, y);
wrapRotateX(rotateX);
wrapRotateY(rotateY);
wrapX(moveX);
wrapY(moveY);
awards.forEach((award, i) => {
const baseRotate = i % 2 === 0 ? 15 : -15;
const strengthX = 8 + i * 2.5;
const strengthY = 6 + i * 2;
const depth = 20 + i * 6;
const extraRotate = gsap.utils.interpolate(-4, 4, x);
const driftX = gsap.utils.interpolate(-strengthX, strengthX, x);
const driftY = gsap.utils.interpolate(-strengthY, strengthY, y);
gsap.to(award, {
x: driftX,
y: driftY,
z: depth,
rotate: baseRotate + extraRotate,
duration: 0.45,
ease: "power2.out",
overwrite: true
});
});
});
awardContainer.addEventListener("pointerleave", function () {
wrapRotateX(0);
wrapRotateY(0);
wrapX(0);
wrapY(0);
awards.forEach((award, i) => {
const baseRotate = i % 2 === 0 ? 15 : -15;
gsap.to(award, {
x: 0,
y: 0,
z: 0,
rotate: baseRotate,
duration: 0.7,
ease: "power3.out",
overwrite: true
});
});
});
});
document.addEventListener("DOMContentLoaded", function () {
if (typeof gsap === "undefined" || typeof ScrollTrigger === "undefined") return;
gsap.registerPlugin(ScrollTrigger);
const awards = document.querySelectorAll(".awards-wrap img");
if (!awards.length) return;
gsap.set(awards, {
y: -180,
z: -120,
opacity: 0,
rotate: (i) => (i % 2 === 0 ? 18 : -18),
filter: "blur(8px)",
force3D: true
});
gsap.to(awards, {
y: 0,
z: 0,
opacity: 1,
rotate: (i) => (i % 2 === 0 ? 15 : -15),
filter: "blur(0px)",
duration: 1.15,
ease: "power3.out",
stagger: 0.1,
force3D: true,
scrollTrigger: {
trigger: ".award-container",
start: "top 82%",
once: true
}
});
});
document.addEventListener("DOMContentLoaded", function () {
const showcaseSlider = document.querySelector(".showcase-slider");
const sliderWrap = document.querySelector(".slider-wrap");
const showcaseItems = document.querySelectorAll(".slider-wrap .showcase-item");
if (!showcaseSlider || !sliderWrap || !showcaseItems.length) return;
if (window.innerWidth <= 991) return;
gsap.set(showcaseSlider, {
perspective: 1200
});
gsap.set(sliderWrap, {
transformStyle: "preserve-3d",
transformPerspective: 1200
});
gsap.set(showcaseItems, {
transformStyle: "preserve-3d"
});
const wrapRotateX = gsap.quickTo(sliderWrap, "rotationX", {
duration: 0.8,
ease: "power3.out"
});
const wrapRotateY = gsap.quickTo(sliderWrap, "rotationY", {
duration: 0.8,
ease: "power3.out"
});
const wrapY = gsap.quickTo(sliderWrap, "y", {
duration: 0.8,
ease: "power3.out"
});
function handleMove(e) {
const rect = showcaseSlider.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
const rotateY = gsap.utils.interpolate(-8, 8, x);
const rotateX = gsap.utils.interpolate(6, -6, y);
const moveWrapY = gsap.utils.interpolate(8, -8, y);
wrapRotateX(rotateX);
wrapRotateY(rotateY);
wrapY(moveWrapY);
showcaseItems.forEach((item) => {
const img = item.querySelector("img");
if (!img) return;
const isCenter = item.classList.contains("center");
const strength = isCenter ? 22 : 10;
const zDepth = isCenter ? 35 : 0;
const scale = isCenter ? 1.03 : 1;
const moveX = gsap.utils.interpolate(-strength, strength, x);
const moveY = gsap.utils.interpolate(-strength, strength, y);
const imgRotate = isCenter
? gsap.utils.interpolate(-1.5, 1.5, x)
: gsap.utils.interpolate(-0.6, 0.6, x);
gsap.to(item, {
z: zDepth,
scale: scale,
duration: 0.7,
ease: "power3.out",
overwrite: true
});
gsap.to(img, {
x: moveX,
y: moveY,
rotateZ: imgRotate,
duration: 0.7,
ease: "power3.out",
overwrite: true
});
});
}
function handleLeave() {
wrapRotateX(0);
wrapRotateY(0);
wrapY(0);
showcaseItems.forEach((item) => {
const img = item.querySelector("img");
if (!img) return;
gsap.to(item, {
z: 0,
scale: 1,
duration: 0.9,
ease: "power3.out",
overwrite: true
});
gsap.to(img, {
x: 0,
y: 0,
rotateZ: 0,
duration: 0.9,
ease: "power3.out",
overwrite: true
});
});
}
showcaseSlider.addEventListener("pointermove", handleMove);
showcaseSlider.addEventListener("pointerleave", handleLeave);
});
(function ($) {
"use strict";
$(document).ready(function () {
// ===== Menu Toggle =====
$(".menu-trigger").click(() => $(".slide-menu").addClass("active"));
$(".menu-close").click(() => $(".slide-menu").removeClass("active"));
// ===== Sticky Header =====
// ===== Hide Header on Scroll Down / Show on Scroll Up =====
let lastScrollTop = 0;
$(window).on("scroll", () => {
const currentScroll = $(window).scrollTop();
const header = $(".header");
header.toggleClass("sticky", currentScroll >= 100);
if (currentScroll > lastScrollTop && currentScroll > 120) {
header.addClass("header-hidden");
} else {
header.removeClass("header-hidden");
}
lastScrollTop = currentScroll <= 0 ? 0 : currentScroll;
});
// ===== Infinite Brand Slider =====
const brandTrack = document.querySelector(".slider-track");
if (brandTrack) {
brandTrack.innerHTML += brandTrack.innerHTML;
const totalBrandWidth = brandTrack.scrollWidth / 2;
gsap.to(brandTrack, {
x: -totalBrandWidth,
duration: 20,
ease: "none",
repeat: -1
});
}
// ===== Owl Carousel Sliders =====
// ===== Inspiration Overlay Slider =====
$('.showcase-gellary').owlCarousel({
loop: true,
center: true,
margin: 0,
nav: false,
dots: false,
smartSpeed: 850,
autoplay: false,
autoplayTimeout: 63200,
autoplayHoverPause: true,
mouseDrag: true,
touchDrag: true,
pullDrag: true,
responsive: {
0: {
items: 1.15,
stagePadding: 30
},
768: {
items: 2.2,
stagePadding: 40
},
1024: {
items: 3,
stagePadding: 50,
margin: 15
}
}
});
});
// ===== Portfolio Filter (Multi-Select) =====
const filterButtons = document.querySelectorAll(".portfolio-filter button");
const projectCards = document.querySelectorAll(".project-card");
let activeFilters = new Set();
filterButtons.forEach(btn => {
btn.addEventListener("click", () => {
const filter = btn.dataset.filter;
if (filter === "all") {
activeFilters.clear();
filterButtons.forEach(b => b.classList.remove("active"));
btn.classList.add("active");
projectCards.forEach(c => c.classList.remove("hide"));
return;
}
activeFilters.has(filter) ? activeFilters.delete(filter) : activeFilters.add(filter);
btn.classList.toggle("active");
document.querySelector(".portfolio-filter button[data-filter='all']").classList.remove("active");
projectCards.forEach(card => {
const matches = [...activeFilters].some(f => card.classList.contains(f));
card.classList.toggle("hide", activeFilters.size > 0 && !matches);
});
});
});
// ===== Portfolio Filter (Multi-Select) =====
// Beyond the Brief Card Infinite Slider Start
// ===== Flip Card =====
let currentCard = null;
function handleFlip(card) {
if (currentCard === card) return card.classList.remove("active"), currentCard = null;
if (currentCard) currentCard.classList.remove("active");
card.classList.add("active");
currentCard = card;
}
// ===== Branding Gallery Hover Effect =====
document.querySelectorAll(".branding-list h2").forEach(item => {
const hoverImage = document.querySelector(".hover-image");
const hoverImgTag = hoverImage.querySelector("img");
item.addEventListener("mouseenter", () => {
hoverImgTag.src = item.dataset.img;
hoverImage.style.opacity = 1;
});
item.addEventListener("mouseleave", () => hoverImage.style.opacity = 0);
item.addEventListener("mousemove", e => {
hoverImage.style.left = e.clientX + "px";
hoverImage.style.top = e.clientY + "px";
});
});
// ===== Text Vertical Slide =====
window.addEventListener("load", () => {
document.querySelectorAll(".shkVrtx91A").forEach(container => {
const items = container.querySelectorAll(".shk-vrtx-item-91A");
if (!items.length) return;
container.appendChild(items[0].cloneNode(true));
const itemHeight = items[0].offsetHeight;
const tl = gsap.timeline({ repeat: -1 });
items.forEach((_, i) => {
tl.to(container, { y: -itemHeight * (i + 1), duration: 0.5, ease: "power2.inOut" })
.to({}, { duration: 1.2 }); // pause
});
});
});
// ===== Scroll-triggered GSAP Animations =====
gsap.registerPlugin(ScrollTrigger, MorphSVGPlugin);
// Awards fade in
gsap.to(".awards-wrap", {
opacity: 1,
y: 0,
duration: 1,
ease: "power3.out",
scrollTrigger: {
trigger: ".awards-wrap",
start: "top 80%",
toggleActions: "play none none none"
}
});
// Showcase Items
gsap.utils.toArray(".showcase-item").forEach(item => {
gsap.set(item, { opacity: 0, y: 20 });
gsap.to(item, {
opacity: 1,
y: 0,
stagger: 0.12,
ease: "power1.out",
scrollTrigger: {
trigger: ".slider-wrap",
start: "top 75%",
end: "bottom 25%",
toggleActions: "play none none none"
}
});
});
// Footer Shake Animation
const down = 'M0-0.3C0-0.3,464,156,1139,156S2278-0.3,2278-0.3V683H0V-0.3z';
const center = 'M0-0.3C0-0.3,464,0,1139,0s1139-0.3,1139-0.3V683H0V-0.3z';
ScrollTrigger.create({
trigger: '.footer',
start: 'top bottom',
toggleActions: 'play pause resume reverse',
onEnter: self => {
const variation = self.getVelocity() / 10000;
gsap.fromTo('#bouncy-path', { morphSVG: down }, {
duration: 2,
morphSVG: center,
ease: `elastic.out(${1 + variation}, ${1 - variation})`,
overwrite: 'true'
});
}
});
// ===== Interactive Movement Effects =====
function addPointerEffect(elements, options) {
elements.forEach(el => {
const rotX = gsap.quickTo(el, "rotationX", options);
const rotY = gsap.quickTo(el, "rotationY", options);
const moveX = gsap.quickTo(el, "x", options);
const moveY = gsap.quickTo(el, "y", options);
const scale = gsap.quickTo(el, "scale", options);
el.addEventListener("pointermove", e => {
const rect = el.getBoundingClientRect();
const x = (e.clientX - rect.left) / rect.width;
const y = (e.clientY - rect.top) / rect.height;
rotX(gsap.utils.interpolate(options.rotXMin, options.rotXMax, y));
rotY(gsap.utils.interpolate(options.rotYMin, options.rotYMax, x));
moveX(gsap.utils.interpolate(options.moveXMin, options.moveXMax, x));
moveY(gsap.utils.interpolate(options.moveYMin, options.moveYMax, y));
scale(options.scaleValue);
});
el.addEventListener("pointerleave", () => {
rotX(0); rotY(0); moveX(0); moveY(0); scale(1);
});
});
}
addPointerEffect(document.querySelectorAll(".showcase-item"), {
duration: 0.6, ease: "power4.out",
rotXMin: 25, rotXMax: -25, rotYMin: -25, rotYMax: 25,
moveXMin: -40, moveXMax: 40, moveYMin: -40, moveYMax: 40,
scaleValue: 1.08
});
addPointerEffect(document.querySelectorAll(".awards-wrap img"), {
duration: 0.3, ease: "power3.out",
rotXMin: 35, rotXMax: -35, rotYMin: -35, rotYMax: 35,
moveXMin: -25, moveXMax: 25, moveYMin: -25, moveYMax: 25,
scaleValue: 1.12
});
addPointerEffect(document.querySelectorAll(".team-card"), {
duration: 0.2, ease: "power3.out",
rotXMin: 25, rotXMax: -25, rotYMin: -25, rotYMax: 25,
moveXMin: 0, moveXMax: 0, moveYMin: 0, moveYMax: 0,
scaleValue: 1.1
});
// ===== Falling Buttons Animation =====
document.querySelectorAll(".ct-falling-btn-wrap a").forEach(btn => {
const randomX = gsap.utils.random(-50, 50);
const randomRot = gsap.utils.random(-25, 25);
const randomDelay = gsap.utils.random(0, 0.5);
gsap.fromTo(btn,
{ y: -200, x: 0, rotation: 0, opacity: 0 },
{
y: 0,
x: randomX,
rotation: randomRot,
opacity: 1,
duration: 1.2,
ease: "power3.out",
delay: randomDelay,
scrollTrigger: {
trigger: ".branding-area",
start: "top 85%",
toggleActions: "play none none none"
}
}
);
});
})(jQuery);
// Text Vertical Slide Effect Start
document.addEventListener("DOMContentLoaded", function () {
const container = document.getElementById("ctVertical");
const items = container.children;
container.appendChild(items[0].cloneNode(true));
const itemHeight = items[0].offsetHeight;
const tl = gsap.timeline({ repeat: -1 });
for (let i = 0; i < items.length; i++) {
tl.to(container, {
y: -itemHeight * i,
duration: 0.6,
ease: "power2.inOut"
})
.to({}, { duration: 1.5 }); // ⏸ pause time
}
});
// Text Vertical Slide Effect End
// Falling buttons on About page
gsap.registerPlugin(ScrollTrigger);
ScrollTrigger.create({
trigger: ".branding-area",
start: "top 99%",
once: true,
onEnter: () => {
const buttons = document.querySelectorAll(".ct-falling-btn-wrap a");
buttons.forEach((btn) => {
const randomX = gsap.utils.random(-70, 70);
const randomY = gsap.utils.random(0, 20);
const randomRot = gsap.utils.random(-15, 15);
const randomDelay = gsap.utils.random(0, 0.4);
gsap.fromTo(
btn,
{
y: gsap.utils.random(-520, -400),
x: 0,
rotation: gsap.utils.random(-8, 8),
opacity: 0,
},
{
y: randomY,
x: randomX,
rotation: randomRot,
opacity: 1,
duration: gsap.utils.random(1.6, 2.1),
ease: "expo.out",
delay: randomDelay,
overwrite: "auto"
}
);
});
}
});