mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-19 20:34:45 +08:00
175 lines
5.6 KiB
JavaScript
175 lines
5.6 KiB
JavaScript
// 2026 Horizons - Interactive Features
|
|
|
|
document.addEventListener('DOMContentLoaded', function() {
|
|
// Theme Toggle
|
|
const themeToggle = document.getElementById('themeToggle');
|
|
const themeIcon = themeToggle.querySelector('i');
|
|
|
|
// Check for saved theme or prefer-color-scheme
|
|
const savedTheme = localStorage.getItem('theme');
|
|
const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
|
|
|
if (savedTheme === 'dark' || (!savedTheme && prefersDark)) {
|
|
document.documentElement.setAttribute('data-theme', 'dark');
|
|
themeIcon.className = 'fas fa-sun';
|
|
}
|
|
|
|
themeToggle.addEventListener('click', function() {
|
|
const currentTheme = document.documentElement.getAttribute('data-theme');
|
|
|
|
if (currentTheme === 'dark') {
|
|
document.documentElement.removeAttribute('data-theme');
|
|
themeIcon.className = 'fas fa-moon';
|
|
localStorage.setItem('theme', 'light');
|
|
} else {
|
|
document.documentElement.setAttribute('data-theme', 'dark');
|
|
themeIcon.className = 'fas fa-sun';
|
|
localStorage.setItem('theme', 'dark');
|
|
}
|
|
});
|
|
|
|
// Smooth scroll for navigation links
|
|
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
|
|
anchor.addEventListener('click', function(e) {
|
|
e.preventDefault();
|
|
|
|
const targetId = this.getAttribute('href');
|
|
if (targetId === '#') return;
|
|
|
|
const targetElement = document.querySelector(targetId);
|
|
if (targetElement) {
|
|
const headerHeight = document.querySelector('.navbar').offsetHeight;
|
|
const targetPosition = targetElement.offsetTop - headerHeight - 20;
|
|
|
|
window.scrollTo({
|
|
top: targetPosition,
|
|
behavior: 'smooth'
|
|
});
|
|
}
|
|
});
|
|
});
|
|
|
|
// Navbar scroll effect
|
|
const navbar = document.querySelector('.navbar');
|
|
let lastScrollTop = 0;
|
|
|
|
window.addEventListener('scroll', function() {
|
|
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
|
|
|
|
// Hide/show navbar on scroll
|
|
if (scrollTop > lastScrollTop && scrollTop > 100) {
|
|
navbar.style.transform = 'translateY(-100%)';
|
|
} else {
|
|
navbar.style.transform = 'translateY(0)';
|
|
}
|
|
|
|
lastScrollTop = scrollTop;
|
|
|
|
// Add shadow when scrolled
|
|
if (scrollTop > 10) {
|
|
navbar.style.boxShadow = 'var(--shadow-md)';
|
|
} else {
|
|
navbar.style.boxShadow = 'none';
|
|
}
|
|
});
|
|
|
|
// Animate elements on scroll
|
|
const observerOptions = {
|
|
threshold: 0.1,
|
|
rootMargin: '0px 0px -50px 0px'
|
|
};
|
|
|
|
const observer = new IntersectionObserver(function(entries) {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
entry.target.classList.add('fade-in');
|
|
observer.unobserve(entry.target);
|
|
}
|
|
});
|
|
}, observerOptions);
|
|
|
|
// Observe elements to animate
|
|
document.querySelectorAll('.trend-card, .opportunity-card, .challenge-card, .highlight-card').forEach(el => {
|
|
observer.observe(el);
|
|
});
|
|
|
|
// Stats counter animation
|
|
const stats = document.querySelectorAll('.stat-number');
|
|
|
|
const statsObserver = new IntersectionObserver(function(entries) {
|
|
entries.forEach(entry => {
|
|
if (entry.isIntersecting) {
|
|
const stat = entry.target;
|
|
const targetValue = parseInt(stat.textContent);
|
|
let currentValue = 0;
|
|
const increment = targetValue / 50;
|
|
const duration = 1500;
|
|
const stepTime = Math.floor(duration / 50);
|
|
|
|
const timer = setInterval(() => {
|
|
currentValue += increment;
|
|
if (currentValue >= targetValue) {
|
|
stat.textContent = targetValue;
|
|
clearInterval(timer);
|
|
} else {
|
|
stat.textContent = Math.floor(currentValue);
|
|
}
|
|
}, stepTime);
|
|
|
|
statsObserver.unobserve(stat);
|
|
}
|
|
});
|
|
}, { threshold: 0.5 });
|
|
|
|
stats.forEach(stat => {
|
|
statsObserver.observe(stat);
|
|
});
|
|
|
|
// Hover effects for cards
|
|
document.querySelectorAll('.trend-card, .opportunity-card, .challenge-card').forEach(card => {
|
|
card.addEventListener('mouseenter', function() {
|
|
this.style.zIndex = '10';
|
|
});
|
|
|
|
card.addEventListener('mouseleave', function() {
|
|
this.style.zIndex = '1';
|
|
});
|
|
});
|
|
|
|
// Current year in footer
|
|
const currentYear = new Date().getFullYear();
|
|
const yearElement = document.querySelector('.copyright p');
|
|
if (yearElement) {
|
|
yearElement.textContent = yearElement.textContent.replace('2026', currentYear);
|
|
}
|
|
|
|
// Initialize animations
|
|
setTimeout(() => {
|
|
document.body.style.opacity = '1';
|
|
}, 100);
|
|
});
|
|
|
|
// Add CSS for initial load
|
|
const style = document.createElement('style');
|
|
style.textContent = `
|
|
body {
|
|
opacity: 0;
|
|
transition: opacity 0.5s ease-in;
|
|
}
|
|
|
|
.fade-in {
|
|
animation: fadeIn 0.8s ease-out forwards;
|
|
}
|
|
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20px);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
`;
|
|
document.head.appendChild(style); |