php-manager-website/script.js

358 lines
9.4 KiB
JavaScript

/**
* DevTools 官网交互脚本
* 支持主页、PHPer、EasyShell 页面
*/
document.addEventListener('DOMContentLoaded', () => {
// 初始化所有功能
initScreenshotTabs();
initFAQ();
initScrollAnimations();
initMobileMenu();
initSmoothScroll();
initNavbarScroll();
});
/**
* 截图标签切换
*/
function initScreenshotTabs() {
const tabs = document.querySelectorAll('.tab-btn');
const images = document.querySelectorAll('.screenshot-img');
if (!tabs.length || !images.length) return;
tabs.forEach(tab => {
tab.addEventListener('click', () => {
const target = tab.dataset.tab;
// 切换标签状态
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
// 切换图片
images.forEach(img => {
if (img.dataset.tab === target) {
img.classList.add('active');
} else {
img.classList.remove('active');
}
});
});
});
}
/**
* FAQ 折叠面板
*/
function initFAQ() {
const faqItems = document.querySelectorAll('.faq-item');
if (!faqItems.length) return;
faqItems.forEach(item => {
const question = item.querySelector('.faq-question');
question.addEventListener('click', () => {
// 关闭其他展开的项目
faqItems.forEach(other => {
if (other !== item && other.classList.contains('active')) {
other.classList.remove('active');
}
});
// 切换当前项目
item.classList.toggle('active');
});
});
}
/**
* 滚动动画
*/
function initScrollAnimations() {
const observerOptions = {
root: null,
rootMargin: '0px',
threshold: 0.1
};
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('visible');
}
});
}, observerOptions);
// 观察需要动画的元素
const animatedElements = document.querySelectorAll(
'.feature-card, .faq-item, .table-row:not(.table-header), .product-card, .banner-content, .platform-card, .shortcut-item, .comparison-row'
);
animatedElements.forEach((el, index) => {
// 为每组元素设置递增的延迟
const delay = Math.min(index * 0.05, 0.5);
el.style.transitionDelay = `${delay}s`;
observer.observe(el);
});
}
/**
* 移动端菜单
*/
function initMobileMenu() {
const menuBtn = document.querySelector('.mobile-menu-btn');
const navLinks = document.querySelector('.nav-links');
if (!menuBtn || !navLinks) return;
menuBtn.addEventListener('click', () => {
menuBtn.classList.toggle('active');
navLinks.classList.toggle('mobile-open');
});
// 点击链接后关闭菜单
navLinks.querySelectorAll('a').forEach(link => {
link.addEventListener('click', () => {
menuBtn.classList.remove('active');
navLinks.classList.remove('mobile-open');
});
});
// 点击页面其他地方关闭菜单
document.addEventListener('click', (e) => {
if (!menuBtn.contains(e.target) && !navLinks.contains(e.target)) {
menuBtn.classList.remove('active');
navLinks.classList.remove('mobile-open');
}
});
}
/**
* 平滑滚动
*/
function initSmoothScroll() {
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function(e) {
const href = this.getAttribute('href');
if (href === '#') return;
e.preventDefault();
const target = document.querySelector(href);
if (target) {
target.scrollIntoView({
behavior: 'smooth',
block: 'start'
});
}
});
});
}
/**
* 导航栏滚动效果
*/
function initNavbarScroll() {
const navbar = document.querySelector('.navbar');
if (!navbar) return;
let lastScroll = 0;
window.addEventListener('scroll', () => {
const currentScroll = window.pageYOffset;
if (currentScroll > 100) {
navbar.style.boxShadow = '0 4px 30px rgba(0, 0, 0, 0.3)';
navbar.style.background = 'rgba(8, 12, 20, 0.95)';
} else {
navbar.style.boxShadow = 'none';
navbar.style.background = 'rgba(8, 12, 20, 0.85)';
}
lastScroll = currentScroll;
});
}
/**
* 产品卡片悬停效果增强
*/
document.querySelectorAll('.product-card').forEach(card => {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-8px)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
/**
* 浮动卡片交互效果
*/
document.querySelectorAll('.float-card').forEach(card => {
card.addEventListener('mouseenter', function() {
// 暂停动画
this.style.animationPlayState = 'paused';
});
card.addEventListener('mouseleave', function() {
// 恢复动画
this.style.animationPlayState = 'running';
});
});
/**
* 按钮点击波纹效果
*/
document.querySelectorAll('.btn').forEach(btn => {
btn.addEventListener('click', function(e) {
const ripple = document.createElement('span');
const rect = this.getBoundingClientRect();
const size = Math.max(rect.width, rect.height);
const x = e.clientX - rect.left - size / 2;
const y = e.clientY - rect.top - size / 2;
ripple.style.cssText = `
position: absolute;
width: ${size}px;
height: ${size}px;
left: ${x}px;
top: ${y}px;
background: rgba(255, 255, 255, 0.3);
border-radius: 50%;
transform: scale(0);
animation: ripple 0.6s ease-out;
pointer-events: none;
`;
this.style.position = 'relative';
this.style.overflow = 'hidden';
this.appendChild(ripple);
setTimeout(() => ripple.remove(), 600);
});
});
// 添加波纹动画样式
const style = document.createElement('style');
style.textContent = `
@keyframes ripple {
to {
transform: scale(4);
opacity: 0;
}
}
`;
document.head.appendChild(style);
/**
* 图片懒加载
*/
function initLazyLoad() {
const images = document.querySelectorAll('img[data-src]');
if ('IntersectionObserver' in window) {
const imageObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
img.src = img.dataset.src;
img.removeAttribute('data-src');
imageObserver.unobserve(img);
}
});
});
images.forEach(img => imageObserver.observe(img));
} else {
// 降级处理
images.forEach(img => {
img.src = img.dataset.src;
});
}
}
/**
* 页面加载完成后的初始化
*/
window.addEventListener('load', () => {
// 移除加载状态
document.body.classList.add('loaded');
// 初始化懒加载
initLazyLoad();
});
/**
* 复制代码功能(如果需要)
*/
function copyToClipboard(text) {
if (navigator.clipboard) {
navigator.clipboard.writeText(text).then(() => {
showToast('已复制到剪贴板');
});
} else {
// 降级处理
const textarea = document.createElement('textarea');
textarea.value = text;
document.body.appendChild(textarea);
textarea.select();
document.execCommand('copy');
document.body.removeChild(textarea);
showToast('已复制到剪贴板');
}
}
/**
* 显示提示消息
*/
function showToast(message) {
const toast = document.createElement('div');
toast.className = 'toast';
toast.textContent = message;
toast.style.cssText = `
position: fixed;
bottom: 24px;
left: 50%;
transform: translateX(-50%);
background: rgba(16, 185, 129, 0.9);
color: white;
padding: 12px 24px;
border-radius: 8px;
font-size: 14px;
z-index: 9999;
animation: toastIn 0.3s ease, toastOut 0.3s ease 2s forwards;
`;
document.body.appendChild(toast);
setTimeout(() => toast.remove(), 2500);
}
// Toast 动画样式
const toastStyle = document.createElement('style');
toastStyle.textContent = `
@keyframes toastIn {
from {
opacity: 0;
transform: translateX(-50%) translateY(20px);
}
to {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
}
@keyframes toastOut {
from {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
to {
opacity: 0;
transform: translateX(-50%) translateY(-20px);
}
}
`;
document.head.appendChild(toastStyle);