mirror of
https://gitee.com/wanwujie/deer-flow
synced 2026-04-20 12:54:45 +08:00
feat: add new demo
This commit is contained in:
@@ -0,0 +1,175 @@
|
||||
// 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);
|
||||
Reference in New Issue
Block a user