Files
FTCWebsite/static/js/scripts.js
abhiramtx 4b63214eea Add stars to all pages and adjust contact and sponsor page content
Update initStars function to include new sections, and reposition text elements in contact and sponsors HTML templates.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: 75bceff7-98f2-4f6e-ae8e-e735399a1fe8
Replit-Commit-Checkpoint-Type: full_checkpoint
Replit-Commit-Event-Id: 551d53d0-8bb9-484f-a2af-ac206e52585e
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d0a1d46d-d203-4308-bc6a-312ac7c0243b/75bceff7-98f2-4f6e-ae8e-e735399a1fe8/a9ZWif3
2025-11-09 00:18:07 +00:00

414 lines
12 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();
initFloatingElements();
initPageLoadAnimation();
initScrollIndicator();
initStars();
});
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
}
});
}
}
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 cards = document.querySelectorAll('.value-card');
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 + '%';
});
}
function initStars() {
const sections = document.querySelectorAll('.home-info, .contributors, .contact, .sponsors, .competitions');
sections.forEach(section => {
const starContainer = document.createElement('div');
starContainer.className = 'stars-container';
const sectionHeight = section.offsetHeight;
const viewportWidth = window.innerWidth;
const numStars = Math.floor((viewportWidth * sectionHeight) / 40000);
for (let i = 0; i < numStars; i++) {
const star = document.createElement('div');
star.className = 'star';
const size = Math.random() * 3 + 1;
const x = Math.random() * 100;
const y = Math.random() * 100;
const duration = Math.random() * 3 + 2;
const delay = Math.random() * 3;
star.style.width = size + 'px';
star.style.height = size + 'px';
star.style.left = x + '%';
star.style.top = y + '%';
star.style.setProperty('--duration', duration + 's');
star.style.setProperty('--delay', delay + 's');
starContainer.appendChild(star);
}
section.appendChild(starContainer);
});
}