Update
This commit is contained in:
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,342 @@
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
$(document).ready(function () {
|
||||
|
||||
// ===== Menu Toggle =====
|
||||
$(".menu-trigger").click(() => $(".slide-menu").addClass("active"));
|
||||
$(".menu-close").click(() => $(".slide-menu").removeClass("active"));
|
||||
|
||||
// ===== Sticky Header =====
|
||||
$(window).on("scroll", () => {
|
||||
const scroll = $(window).scrollTop();
|
||||
$(".header").toggleClass("sticky", scroll >= 100);
|
||||
});
|
||||
|
||||
// ===== 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").owlCarousel({
|
||||
loop: true,
|
||||
margin: 10,
|
||||
nav: false,
|
||||
items: 1,
|
||||
stagePadding: 45,
|
||||
autoplay: true,
|
||||
autoplayTimeout: 5000,
|
||||
autoplayHoverPause: true,
|
||||
dots: true
|
||||
});
|
||||
|
||||
$(".showcase-gellary").owlCarousel({
|
||||
loop: true,
|
||||
margin: 15,
|
||||
nav: false,
|
||||
items: 1,
|
||||
stagePadding: 50,
|
||||
autoplay: true,
|
||||
autoplayTimeout: 2000,
|
||||
autoplayHoverPause: true,
|
||||
dots: false
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// ===== 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
|
||||
gsap.registerPlugin(Draggable);
|
||||
|
||||
const teamTrack = document.querySelector(".team-track");
|
||||
|
||||
if (teamTrack) {
|
||||
// 1. Duplicate content for seamless loop
|
||||
teamTrack.innerHTML += teamTrack.innerHTML;
|
||||
const totalTeamWidth = teamTrack.scrollWidth / 2;
|
||||
|
||||
// 2. Create the base animation
|
||||
const teamTween = gsap.to(teamTrack, {
|
||||
x: -totalTeamWidth,
|
||||
duration: 25,
|
||||
ease: "none",
|
||||
repeat: -1
|
||||
});
|
||||
|
||||
// 3. Track scroll direction for timeScale
|
||||
let lastScrollY = window.scrollY;
|
||||
window.addEventListener("scroll", () => {
|
||||
const currentY = window.scrollY;
|
||||
// Smoothly transition the direction change
|
||||
gsap.to(teamTween, { timeScale: currentY > lastScrollY ? 1 : -1, overwrite: true });
|
||||
lastScrollY = currentY;
|
||||
});
|
||||
|
||||
// 4. Add Drag Functionality
|
||||
// We use a dummy element (proxy) to capture drag logic
|
||||
const proxy = document.createElement("div");
|
||||
|
||||
Draggable.create(proxy, {
|
||||
type: "x",
|
||||
trigger: teamTrack, // Dragging the track triggers the logic
|
||||
onPress() {
|
||||
this.startProgress = teamTween.progress();
|
||||
},
|
||||
onDrag: function() {
|
||||
// Calculate how far we've dragged relative to the width
|
||||
const change = (this.startX - this.x) / totalTeamWidth;
|
||||
let newProgress = this.startProgress + change;
|
||||
|
||||
// Wrap the progress so it stays between 0 and 1
|
||||
teamTween.progress(gsap.utils.wrap(0, 1, newProgress));
|
||||
},
|
||||
onRelease: function() {
|
||||
// Optional: Resume the animation if you want it to keep moving
|
||||
// teamTween.play();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 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
|
||||
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user