/**
* Modern About Page JavaScript
* This file contains JavaScript functionality for the about page
*/
document.addEventListener('DOMContentLoaded', function() {
// Initialize 3D background if it exists
initializeBackground();
// Animate cards and elements on scroll
initializeScrollAnimations();
// Initialize counter animation for stats
initializeCounters();
// Make navbar transparent/solid on scroll
handleNavbarScroll();
});
/**
* Initialize the 3D animated background
*/
function initializeBackground() {
// Create background container if it doesn't exist
if (!document.querySelector('.bg-animation')) {
const bgAnimation = document.createElement('div');
bgAnimation.className = 'bg-animation';
const bgGradient = document.createElement('div');
bgGradient.className = 'bg-gradient';
const bgShapes = document.createElement('div');
bgShapes.className = 'bg-shapes';
// Create animated shapes
for (let i = 1; i <= 4; i++) {
const shape = document.createElement('div');
shape.className = `shape shape-${i}`;
bgShapes.appendChild(shape);
}
bgAnimation.appendChild(bgGradient);
bgAnimation.appendChild(bgShapes);
document.body.insertBefore(bgAnimation, document.body.firstChild);
}
// Add parallax effect to shapes
const shapes = document.querySelectorAll('.shape');
document.addEventListener('mousemove', function(e) {
const x = e.clientX / window.innerWidth;
const y = e.clientY / window.innerHeight;
shapes.forEach((shape, index) => {
const speed = (index + 1) * 10;
const offsetX = (0.5 - x) * speed;
const offsetY = (0.5 - y) * speed;
shape.style.transform = `translate(${offsetX}px, ${offsetY}px)`;
});
});
}
/**
* Initialize animations for elements on scroll
*/
function initializeScrollAnimations() {
// Elements to animate on scroll
const animatedElements = [
'.feature-card',
'.team-card',
'.testimonial-card',
'.stat-card',
'.mission-content',
'.mission-image-container',
'.about-image-container'
];
// If IntersectionObserver is supported
if ('IntersectionObserver' in window) {
const elementObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('animated');
// Stop observing after animation
elementObserver.unobserve(entry.target);
}
});
}, {
threshold: 0.1,
rootMargin: '0px 0px -100px 0px'
});
// Get all elements to animate
animatedElements.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
elementObserver.observe(element);
});
});
} else {
// Fallback for browsers that don't support IntersectionObserver
animatedElements.forEach(selector => {
document.querySelectorAll(selector).forEach(element => {
element.classList.add('animated');
});
});
}
}
/**
* Initialize counter animation for stats
*/
function initializeCounters() {
const statNumbers = document.querySelectorAll('.stat-number');
// If IntersectionObserver is supported
if ('IntersectionObserver' in window) {
const counterObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const target = entry.target;
const targetValue = parseInt(target.getAttribute('data-count'));
// Animate counter
animateCounter(target, targetValue);
// Stop observing after animation
counterObserver.unobserve(target);
}
});
}, {
threshold: 0.5
});
// Observe each counter
statNumbers.forEach(counter => {
// Save target value as data attribute
const value = counter.textContent.replace(/\D/g, '');
counter.setAttribute('data-count', value);
counter.textContent = '0';
counterObserver.observe(counter);
});
} else {
// Fallback for browsers that don't support IntersectionObserver
statNumbers.forEach(counter => {
const targetValue = parseInt(counter.textContent.replace(/\D/g, ''));
animateCounter(counter, targetValue);
});
}
}
/**
* Animate counter from 0 to target value
*/
function animateCounter(element, targetValue) {
let startValue = 0;
const duration = 2000;
const startTime = performance.now();
function updateCounter(currentTime) {
const elapsedTime = currentTime - startTime;
if (elapsedTime < duration) {
const progress = elapsedTime / duration;
// Use easeOutQuad easing function for natural motion
const easedProgress = -Math.pow(progress - 1, 2) + 1;
const currentValue = Math.floor(easedProgress * targetValue);
element.textContent = currentValue;
requestAnimationFrame(updateCounter);
} else {
element.textContent = targetValue;
}
}
requestAnimationFrame(updateCounter);
}
/**
* Handle navbar transparency on scroll
*/
function handleNavbarScroll() {
const navbar = document.querySelector('.navbar');
if (navbar) {
window.addEventListener('scroll', () => {
if (window.scrollY > 50) {
navbar.classList.remove('navbar-transparent');
navbar.classList.add('navbar-solid');
} else {
navbar.classList.add('navbar-transparent');
navbar.classList.remove('navbar-solid');
}
});
// Initial check
if (window.scrollY > 50) {
navbar.classList.remove('navbar-transparent');
navbar.classList.add('navbar-solid');
} else {
navbar.classList.add('navbar-transparent');
navbar.classList.remove('navbar-solid');
}
}
}
/**
* Add parallax effect to hero image
*/
function initializeParallax() {
const heroImage = document.querySelector('.about-image');
const missionImage = document.querySelector('.mission-image');
window.addEventListener('scroll', () => {
if (heroImage) {
const scrollValue = window.scrollY;
heroImage.style.transform = `translateY(${30 - scrollValue * 0.05}px)`;
}
if (missionImage) {
const missionSection = document.querySelector('.about-mission');
const missionTop = missionSection.offsetTop;
const scrollPosition = window.scrollY;
const relativeScroll = scrollPosition - missionTop;
if (relativeScroll > -500 && relativeScroll < 500) {
missionImage.style.transform = `translateY(${relativeScroll * 0.05}px)`;
}
}
});
}
// Initialize parallax effect
setTimeout(initializeParallax, 500);