Implements a new JavaScript function `initStars` that dynamically creates and appends circular star elements to sections with the class `.home-info`. These stars have random sizes, positions, fade animations, and durations, controlled by CSS and keyframes defined in `static/css/styles.css`. The `initStars` function is called on page load via `initPageLoadAnimation`. Replit-Commit-Author: Agent Replit-Commit-Session-Id: 5e584ab0-c340-4432-97ef-1972582b60e9 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: e42678c3-4b34-4047-bd6d-316f729459e1 Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/d0a1d46d-d203-4308-bc6a-312ac7c0243b/5e584ab0-c340-4432-97ef-1972582b60e9/vuYxJMM
423 lines
12 KiB
JavaScript
423 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();
|
|
initMagneticButtons();
|
|
initFloatingElements();
|
|
initPageLoadAnimation();
|
|
initCustomCursor();
|
|
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 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 + '%';
|
|
});
|
|
}
|
|
|
|
function initStars() {
|
|
const sections = document.querySelectorAll('.home-info');
|
|
|
|
sections.forEach(section => {
|
|
const sectionHeight = section.offsetHeight;
|
|
const sectionWidth = section.offsetWidth;
|
|
const numStars = Math.floor((sectionWidth * sectionHeight) / 15000);
|
|
|
|
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');
|
|
|
|
section.appendChild(star);
|
|
}
|
|
});
|
|
}
|