Refine UI by removing blue hover effects, increasing background gradient prominence, and disabling header underline animations. Add four new value cards under the mission statement and restructure the "Meet Our Team" section to be responsive with text on the left and image on the right. Update `replit.md` for documentation and `static/js/scripts.js` to replace `lenis.update()` with `lenis.resize()` in the `ScrollTrigger` refresh event listener. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 5e584ab0-c340-4432-97ef-1972582b60e9 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: cc61dc1c-ba8e-4081-8489-ced839534af9 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d0a1d46d-d203-4308-bc6a-312ac7c0243b/5e584ab0-c340-4432-97ef-1972582b60e9/UhOas7p
405 lines
11 KiB
JavaScript
405 lines
11 KiB
JavaScript
let lenis;
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
gsap.registerPlugin(ScrollTrigger);
|
|
|
|
lenis = new Lenis({
|
|
duration: 1.2,
|
|
easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
|
|
smoothWheel: true,
|
|
smoothTouch: false,
|
|
touchMultiplier: 2,
|
|
infinite: false
|
|
});
|
|
|
|
function raf(time) {
|
|
lenis.raf(time);
|
|
requestAnimationFrame(raf);
|
|
}
|
|
requestAnimationFrame(raf);
|
|
|
|
lenis.on('scroll', ScrollTrigger.update);
|
|
|
|
gsap.ticker.lagSmoothing(0);
|
|
|
|
ScrollTrigger.scrollerProxy(document.body, {
|
|
scrollTop(value) {
|
|
if (arguments.length) {
|
|
lenis.scrollTo(value, { immediate: true });
|
|
}
|
|
return lenis.scroll || 0;
|
|
},
|
|
getBoundingClientRect() {
|
|
return {
|
|
top: 0,
|
|
left: 0,
|
|
width: window.innerWidth,
|
|
height: window.innerHeight
|
|
};
|
|
},
|
|
pinType: document.body.style.transform ? "transform" : "fixed"
|
|
});
|
|
|
|
ScrollTrigger.defaults({ scroller: document.body });
|
|
|
|
ScrollTrigger.addEventListener('refresh', () => lenis.resize());
|
|
ScrollTrigger.refresh();
|
|
|
|
let lastScrollTop = 0;
|
|
const nav = document.querySelector('nav');
|
|
|
|
lenis.on('scroll', ({ scroll }) => {
|
|
if (scroll > 100) {
|
|
nav?.classList.add('scrolled');
|
|
} else {
|
|
nav?.classList.remove('scrolled');
|
|
}
|
|
lastScrollTop = scroll;
|
|
});
|
|
|
|
const currentPath = window.location.pathname;
|
|
|
|
const navLinks = document.querySelectorAll('.nav-item-center, .nav-item-left');
|
|
navLinks.forEach(navItem => {
|
|
const link = navItem.querySelector('a');
|
|
if (link) {
|
|
const linkPath = new URL(link.href).pathname;
|
|
if (linkPath === currentPath || (currentPath === '/' && linkPath === '/')) {
|
|
navItem.classList.add('active');
|
|
}
|
|
}
|
|
});
|
|
|
|
const sidebarLinks = document.querySelectorAll('.sidebar a');
|
|
const hash = window.location.hash;
|
|
if (hash) {
|
|
sidebarLinks.forEach(link => {
|
|
if (link.getAttribute('href') === hash) {
|
|
link.classList.add('active');
|
|
}
|
|
});
|
|
} else if (sidebarLinks.length > 0) {
|
|
sidebarLinks[0].classList.add('active');
|
|
}
|
|
|
|
sidebarLinks.forEach(link => {
|
|
link.addEventListener('click', function() {
|
|
sidebarLinks.forEach(l => l.classList.remove('active'));
|
|
this.classList.add('active');
|
|
});
|
|
});
|
|
|
|
initParallaxEffects();
|
|
initScrollAnimations();
|
|
initMagneticButtons();
|
|
initFloatingElements();
|
|
initPageLoadAnimation();
|
|
initCustomCursor();
|
|
initScrollIndicator();
|
|
});
|
|
|
|
function initParallaxEffects() {
|
|
const heroImage = document.querySelector('.hero-team-image');
|
|
if (heroImage) {
|
|
gsap.to(heroImage, {
|
|
yPercent: 30,
|
|
ease: "none",
|
|
scrollTrigger: {
|
|
trigger: heroImage.parentElement,
|
|
start: "top top",
|
|
end: "bottom top",
|
|
scrub: 1
|
|
}
|
|
});
|
|
}
|
|
|
|
const baseImage = document.querySelector('.overlay-container .base');
|
|
if (baseImage) {
|
|
gsap.to(baseImage, {
|
|
yPercent: 20,
|
|
ease: "none",
|
|
scrollTrigger: {
|
|
trigger: '.bg',
|
|
start: "top top",
|
|
end: "bottom top",
|
|
scrub: 1.5
|
|
}
|
|
});
|
|
}
|
|
|
|
const meetTeamImage = document.querySelector('#meet-our-team');
|
|
if (meetTeamImage) {
|
|
gsap.to(meetTeamImage, {
|
|
yPercent: 15,
|
|
ease: "none",
|
|
scrollTrigger: {
|
|
trigger: '.team-image-wrapper',
|
|
start: "top bottom",
|
|
end: "bottom top",
|
|
scrub: 1
|
|
}
|
|
});
|
|
}
|
|
|
|
const sponsorCards = document.querySelectorAll('.sponsors-card');
|
|
sponsorCards.forEach((card, index) => {
|
|
gsap.to(card, {
|
|
y: -30 * (index % 2 === 0 ? 1 : -1),
|
|
ease: "none",
|
|
scrollTrigger: {
|
|
trigger: card,
|
|
start: "top bottom",
|
|
end: "bottom top",
|
|
scrub: 1
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function initScrollAnimations() {
|
|
const fadeUpElements = document.querySelectorAll('.home-info, .stats-container, .sub-header, .sub-content, .sponsors-container, .hero-image-section, .card, .member-card, .robo-card, .competition-card, .team-section');
|
|
|
|
fadeUpElements.forEach((element, index) => {
|
|
gsap.fromTo(element,
|
|
{
|
|
opacity: 0,
|
|
y: 60
|
|
},
|
|
{
|
|
opacity: 1,
|
|
y: 0,
|
|
duration: 1,
|
|
ease: "power3.out",
|
|
scrollTrigger: {
|
|
trigger: element,
|
|
start: "top 85%",
|
|
end: "top 60%",
|
|
toggleActions: "play none none reverse"
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
const valueCards = document.querySelectorAll('.value-card');
|
|
valueCards.forEach((card, index) => {
|
|
gsap.fromTo(card,
|
|
{
|
|
opacity: 0,
|
|
scale: 0.9,
|
|
y: 40
|
|
},
|
|
{
|
|
opacity: 1,
|
|
scale: 1,
|
|
y: 0,
|
|
duration: 0.8,
|
|
delay: index * 0.15,
|
|
ease: "back.out(1.2)",
|
|
scrollTrigger: {
|
|
trigger: card,
|
|
start: "top 85%",
|
|
toggleActions: "play none none reverse"
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
const statsCards = document.querySelectorAll('.stats-card');
|
|
statsCards.forEach((card, index) => {
|
|
gsap.fromTo(card,
|
|
{
|
|
opacity: 0,
|
|
scale: 0.8,
|
|
y: 40
|
|
},
|
|
{
|
|
opacity: 1,
|
|
scale: 1,
|
|
y: 0,
|
|
duration: 0.8,
|
|
delay: index * 0.1,
|
|
ease: "back.out(1.7)",
|
|
scrollTrigger: {
|
|
trigger: card,
|
|
start: "top 85%",
|
|
toggleActions: "play none none reverse"
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
const headings = document.querySelectorAll('.heading');
|
|
headings.forEach(heading => {
|
|
gsap.fromTo(heading,
|
|
{
|
|
opacity: 0,
|
|
scale: 0.9,
|
|
y: 30
|
|
},
|
|
{
|
|
opacity: 1,
|
|
scale: 1,
|
|
y: 0,
|
|
duration: 0.8,
|
|
ease: "power2.out",
|
|
scrollTrigger: {
|
|
trigger: heading,
|
|
start: "top 90%",
|
|
toggleActions: "play none none reverse"
|
|
}
|
|
}
|
|
);
|
|
});
|
|
|
|
const footerText = document.querySelector('.footer-text');
|
|
if (footerText) {
|
|
gsap.fromTo(footerText,
|
|
{
|
|
opacity: 0,
|
|
y: 40
|
|
},
|
|
{
|
|
opacity: 1,
|
|
y: 0,
|
|
duration: 1.2,
|
|
delay: 0.5,
|
|
ease: "power3.out"
|
|
}
|
|
);
|
|
}
|
|
}
|
|
|
|
function initMagneticButtons() {
|
|
const buttons = document.querySelectorAll('.stats-button, .bottom-center-button, #sponsors-more-button, .home-but');
|
|
|
|
buttons.forEach(button => {
|
|
button.addEventListener('mouseenter', function(e) {
|
|
gsap.to(button, {
|
|
scale: 1.05,
|
|
duration: 0.3,
|
|
ease: "power2.out"
|
|
});
|
|
});
|
|
|
|
button.addEventListener('mouseleave', function(e) {
|
|
gsap.to(button, {
|
|
scale: 1,
|
|
x: 0,
|
|
y: 0,
|
|
duration: 0.3,
|
|
ease: "elastic.out(1, 0.5)"
|
|
});
|
|
});
|
|
|
|
button.addEventListener('mousemove', function(e) {
|
|
const rect = button.getBoundingClientRect();
|
|
const x = e.clientX - rect.left - rect.width / 2;
|
|
const y = e.clientY - rect.top - rect.height / 2;
|
|
|
|
gsap.to(button, {
|
|
x: x * 0.3,
|
|
y: y * 0.3,
|
|
duration: 0.3,
|
|
ease: "power2.out"
|
|
});
|
|
});
|
|
});
|
|
}
|
|
|
|
function initFloatingElements() {
|
|
const memberCards = document.querySelectorAll('.member-card');
|
|
memberCards.forEach((card, index) => {
|
|
gsap.to(card, {
|
|
y: -10,
|
|
duration: 2 + (index % 3) * 0.5,
|
|
repeat: -1,
|
|
yoyo: true,
|
|
ease: "sine.inOut",
|
|
delay: index * 0.2
|
|
});
|
|
});
|
|
|
|
const cards = document.querySelectorAll('.card, .card-sponsors');
|
|
cards.forEach((card, index) => {
|
|
gsap.to(card, {
|
|
y: -8,
|
|
duration: 2.5 + (index % 2) * 0.5,
|
|
repeat: -1,
|
|
yoyo: true,
|
|
ease: "sine.inOut",
|
|
delay: index * 0.15
|
|
});
|
|
});
|
|
}
|
|
|
|
function initPageLoadAnimation() {
|
|
gsap.fromTo('body',
|
|
{ opacity: 0 },
|
|
{ opacity: 1, duration: 0.6, ease: "power2.out" }
|
|
);
|
|
|
|
const nav = document.querySelector('nav');
|
|
if (nav) {
|
|
gsap.fromTo(nav,
|
|
{ y: -100, opacity: 0 },
|
|
{ y: 0, opacity: 1, duration: 0.8, delay: 0.2, ease: "power3.out" }
|
|
);
|
|
}
|
|
|
|
const bg = document.querySelector('.bg');
|
|
if (bg) {
|
|
gsap.fromTo(bg,
|
|
{ scale: 1.1, opacity: 0 },
|
|
{ scale: 1, opacity: 1, duration: 1.5, ease: "power2.out" }
|
|
);
|
|
}
|
|
}
|
|
|
|
function initCustomCursor() {
|
|
if (window.innerWidth <= 850) return;
|
|
|
|
const cursor = document.createElement('div');
|
|
cursor.className = 'custom-cursor';
|
|
document.body.appendChild(cursor);
|
|
|
|
const follower = document.createElement('div');
|
|
follower.className = 'custom-cursor-follower';
|
|
document.body.appendChild(follower);
|
|
|
|
let mouseX = 0, mouseY = 0;
|
|
let followerX = 0, followerY = 0;
|
|
|
|
document.addEventListener('mousemove', (e) => {
|
|
mouseX = e.clientX;
|
|
mouseY = e.clientY;
|
|
cursor.style.left = mouseX + 'px';
|
|
cursor.style.top = mouseY + 'px';
|
|
});
|
|
|
|
function animateFollower() {
|
|
followerX += (mouseX - followerX) * 0.1;
|
|
followerY += (mouseY - followerY) * 0.1;
|
|
follower.style.left = followerX + 'px';
|
|
follower.style.top = followerY + 'px';
|
|
requestAnimationFrame(animateFollower);
|
|
}
|
|
animateFollower();
|
|
|
|
const hoverElements = document.querySelectorAll('a, button, .stats-card, .card, .member-card, .robo-card, .sponsors-card');
|
|
hoverElements.forEach(el => {
|
|
el.addEventListener('mouseenter', () => cursor.classList.add('hover'));
|
|
el.addEventListener('mouseleave', () => cursor.classList.remove('hover'));
|
|
});
|
|
}
|
|
|
|
function initScrollIndicator() {
|
|
const indicator = document.createElement('div');
|
|
indicator.className = 'scroll-indicator';
|
|
document.body.appendChild(indicator);
|
|
|
|
lenis.on('scroll', ({ scroll, limit }) => {
|
|
const progress = (scroll / limit) * 100;
|
|
indicator.style.width = progress + '%';
|
|
});
|
|
}
|