Files
aijianhua/website/js/main.js

514 lines
15 KiB
JavaScript
Raw Normal View History

// 主JavaScript文件 - 爱鉴花官方网站
document.addEventListener('DOMContentLoaded', function() {
// 初始化函数
initWebsite();
});
function initWebsite() {
// 初始化导航栏滚动效果
initNavbarScroll();
// 初始化滚动动画
initScrollAnimation();
// 初始化表单验证
initFormValidation();
// 初始化计数器动画
initCounterAnimation();
// 初始化图片懒加载
initLazyLoading();
// 初始化移动端菜单
initMobileMenu();
// 初始化平滑滚动
initSmoothScroll();
// 初始化悬停动画
initHoverEffects();
// 初始化加载状态
initLoadingStates();
// 初始化页面过渡效果
initPageTransitions();
}
// 导航栏滚动效果
function initNavbarScroll() {
const navbar = document.querySelector('.navbar');
window.addEventListener('scroll', function() {
if (window.scrollY > 100) {
navbar.classList.add('navbar-scrolled');
} else {
navbar.classList.remove('navbar-scrolled');
}
});
}
// 滚动动画效果
function initScrollAnimation() {
const animatedElements = document.querySelectorAll('.card, .feature-icon');
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
entry.target.classList.add('fade-in-up');
observer.unobserve(entry.target);
}
});
}, observerOptions);
animatedElements.forEach(function(element) {
observer.observe(element);
});
}
// 表单验证
function initFormValidation() {
const forms = document.querySelectorAll('form');
forms.forEach(function(form) {
form.addEventListener('submit', function(e) {
if (!validateForm(form)) {
e.preventDefault();
}
});
});
}
function validateForm(form) {
let isValid = true;
const inputs = form.querySelectorAll('input[required], textarea[required]');
inputs.forEach(function(input) {
if (!input.value.trim()) {
showError(input, '此字段为必填项');
isValid = false;
} else if (input.type === 'email' && !isValidEmail(input.value)) {
showError(input, '请输入有效的邮箱地址');
isValid = false;
} else {
clearError(input);
}
});
return isValid;
}
function isValidEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
}
function showError(input, message) {
clearError(input);
const errorDiv = document.createElement('div');
errorDiv.className = 'invalid-feedback';
errorDiv.textContent = message;
input.classList.add('is-invalid');
input.parentNode.appendChild(errorDiv);
}
function clearError(input) {
input.classList.remove('is-invalid');
const errorDiv = input.parentNode.querySelector('.invalid-feedback');
if (errorDiv) {
errorDiv.remove();
}
}
// 计数器动画
function initCounterAnimation() {
const counters = document.querySelectorAll('.counter');
if (counters.length > 0) {
const observer = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
animateCounters();
observer.unobserve(entry.target);
}
});
});
observer.observe(counters[0]);
}
}
function animateCounters() {
const counters = document.querySelectorAll('.counter');
counters.forEach(function(counter) {
const target = parseInt(counter.getAttribute('data-target'));
const duration = 2000; // 2 seconds
const frameDuration = 1000 / 60; // 60fps
const totalFrames = Math.round(duration / frameDuration);
let currentFrame = 0;
const updateCounter = function() {
currentFrame++;
const progress = currentFrame / totalFrames;
const currentValue = Math.round(target * progress);
counter.textContent = currentValue.toLocaleString();
if (currentFrame < totalFrames) {
requestAnimationFrame(updateCounter);
} else {
counter.textContent = target.toLocaleString();
}
};
updateCounter();
});
}
// 图片懒加载
function initLazyLoading() {
if ('IntersectionObserver' in window) {
const lazyImages = document.querySelectorAll('img.lazy-load');
const imageObserver = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
const img = entry.target;
// 确保图片完全加载后显示
img.onload = function() {
img.classList.add('loaded');
};
// 处理data-src属性或直接使用src
if (img.hasAttribute('data-src')) {
img.src = img.getAttribute('data-src');
img.removeAttribute('data-src');
}
imageObserver.unobserve(img);
}
});
}, {
threshold: 0.1,
rootMargin: '50px 0px'
});
lazyImages.forEach(function(img) {
imageObserver.observe(img);
});
} else {
// 浏览器不支持IntersectionObserver时的降级方案
const lazyImages = document.querySelectorAll('img.lazy-load');
lazyImages.forEach(function(img) {
img.classList.add('loaded');
});
}
}
// 移动端菜单处理
function initMobileMenu() {
const navbarToggler = document.querySelector('.navbar-toggler');
const navbarCollapse = document.querySelector('.navbar-collapse');
if (navbarToggler && navbarCollapse) {
navbarToggler.addEventListener('click', function() {
navbarCollapse.classList.toggle('show');
// 添加菜单动画效果
navbarToggler.classList.toggle('active');
});
// 点击菜单项后自动关闭菜单(移动端)
const navLinks = document.querySelectorAll('.navbar-nav .nav-link');
navLinks.forEach(function(link) {
link.addEventListener('click', function() {
if (window.innerWidth < 992) {
navbarCollapse.classList.remove('show');
navbarToggler.classList.remove('active');
}
});
});
}
}
// 平滑滚动效果
function initSmoothScroll() {
// 内部链接平滑滚动
const internalLinks = document.querySelectorAll('a[href^="#"]');
internalLinks.forEach(function(link) {
link.addEventListener('click', function(e) {
e.preventDefault();
const targetId = this.getAttribute('href').substring(1);
const targetElement = document.getElementById(targetId);
if (targetElement) {
const offsetTop = targetElement.offsetTop - 80; // 考虑导航栏高度
window.scrollTo({
top: offsetTop,
behavior: 'smooth'
});
}
});
});
// 返回顶部按钮
const backToTopBtn = document.createElement('button');
backToTopBtn.className = 'back-to-top';
backToTopBtn.innerHTML = '↑';
backToTopBtn.setAttribute('aria-label', '返回顶部');
backToTopBtn.addEventListener('click', function() {
window.scrollTo({
top: 0,
behavior: 'smooth'
});
});
// 滚动时显示/隐藏返回顶部按钮
window.addEventListener('scroll', debounce(function() {
if (window.scrollY > 500) {
backToTopBtn.classList.add('show');
} else {
backToTopBtn.classList.remove('show');
}
}, 100));
document.body.appendChild(backToTopBtn);
}
// 悬停动画效果
function initHoverEffects() {
// 卡片悬停效果
const cards = document.querySelectorAll('.card, .product-card, .news-card');
cards.forEach(function(card) {
card.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-5px) scale(1.02)';
this.style.boxShadow = '0 10px 25px rgba(0, 0, 0, 0.15)';
});
card.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0) scale(1)';
this.style.boxShadow = '0 4px 6px rgba(0, 0, 0, 0.1)';
});
});
// 按钮悬停效果
const buttons = document.querySelectorAll('.btn, .nav-link');
buttons.forEach(function(button) {
button.addEventListener('mouseenter', function() {
this.style.transform = 'translateY(-2px)';
});
button.addEventListener('mouseleave', function() {
this.style.transform = 'translateY(0)';
});
});
}
// 加载状态指示器
function initLoadingStates() {
const forms = document.querySelectorAll('form');
forms.forEach(function(form) {
form.addEventListener('submit', function() {
const submitBtn = this.querySelector('button[type="submit"]');
if (submitBtn) {
submitBtn.disabled = true;
submitBtn.innerHTML = '<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> 处理中...';
// 3秒后恢复按钮状态防止无限加载
setTimeout(function() {
submitBtn.disabled = false;
submitBtn.innerHTML = submitBtn.getAttribute('data-original-text') || '提交';
}, 3000);
}
});
});
// 保存按钮原始文本
document.addEventListener('DOMContentLoaded', function() {
const submitButtons = document.querySelectorAll('button[type="submit"]');
submitButtons.forEach(function(btn) {
btn.setAttribute('data-original-text', btn.textContent);
});
});
}
// 页面过渡效果
function initPageTransitions() {
// 链接点击时的过渡效果
const links = document.querySelectorAll('a:not([href^="#"]):not([href^="javascript"])');
links.forEach(function(link) {
link.addEventListener('click', function(e) {
if (this.href && !this.target && !this.hasAttribute('download')) {
e.preventDefault();
// 添加页面离开动画
document.body.classList.add('page-leaving');
setTimeout(function() {
window.location.href = link.href;
}, 300);
}
});
});
// 页面进入动画
document.body.classList.add('page-entering');
setTimeout(function() {
document.body.classList.remove('page-entering');
}, 300);
}
// 工具函数:防抖
function debounce(func, wait) {
let timeout;
return function() {
const context = this;
const args = arguments;
clearTimeout(timeout);
timeout = setTimeout(function() {
func.apply(context, args);
}, wait);
};
}
// 工具函数:节流
function throttle(func, limit) {
let inThrottle;
return function() {
const args = arguments;
const context = this;
if (!inThrottle) {
func.apply(context, args);
inThrottle = true;
setTimeout(function() {
inThrottle = false;
}, limit);
}
};
}
// 页面性能监控
function monitorPerformance() {
// 页面加载时间
window.addEventListener('load', function() {
const loadTime = performance.timing.loadEventEnd - performance.timing.navigationStart;
console.log('页面加载时间:', loadTime + 'ms');
});
// 最大内容绘制LCP
new PerformanceObserver(function(entryList) {
const entries = entryList.getEntries();
const lastEntry = entries[entries.length - 1];
console.log('LCP:', lastEntry.startTime);
}).observe({type: 'largest-contentful-paint', buffered: true});
}
// 错误监控
function monitorErrors() {
window.addEventListener('error', function(e) {
console.error('JavaScript错误:', e.error);
});
window.addEventListener('unhandledrejection', function(e) {
console.error('未处理的Promise拒绝:', e.reason);
});
}
// 初始化性能和错误监控
monitorPerformance();
monitorErrors();
// 通用JavaScript功能
// 导航栏滚动效果
window.addEventListener('scroll', function() {
const navbar = document.querySelector('.navbar');
if (window.scrollY > 50) {
navbar.classList.add('scrolled');
} else {
navbar.classList.remove('scrolled');
}
});
// 懒加载图片
document.addEventListener('DOMContentLoaded', function() {
const lazyImages = [].slice.call(document.querySelectorAll('img.lazy-load'));
if ('IntersectionObserver' in window) {
let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(entry) {
if (entry.isIntersecting) {
let lazyImage = entry.target;
lazyImage.src = lazyImage.dataset.src || lazyImage.src;
lazyImage.classList.remove('lazy-load');
lazyImageObserver.unobserve(lazyImage);
}
});
});
lazyImages.forEach(function(lazyImage) {
lazyImageObserver.observe(lazyImage);
});
}
});
// 平滑滚动
document.querySelectorAll('a[href^="#"]').forEach(anchor => {
anchor.addEventListener('click', function (e) {
e.preventDefault();
const target = document.querySelector(this.getAttribute('href'));
if (target) {
window.scrollTo({
top: target.offsetTop - 76,
behavior: 'smooth'
});
}
});
});
// 表单验证增强
(function() {
'use strict';
window.addEventListener('load', function() {
// 获取所有表单并阻止默认提交行为
var forms = document.getElementsByClassName('needs-validation');
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
// 动态年份更新
document.addEventListener('DOMContentLoaded', function() {
const yearElements = document.querySelectorAll('.current-year');
const currentYear = new Date().getFullYear();
yearElements.forEach(element => {
element.textContent = currentYear;
});
});