308 lines
10 KiB
JavaScript
308 lines
10 KiB
JavaScript
/* ==================== 玄潮科技 - Main JavaScript ==================== */
|
||
|
||
(function () {
|
||
'use strict';
|
||
|
||
/* ----- DOM Ready ----- */
|
||
document.addEventListener('DOMContentLoaded', function () {
|
||
initMobileMenu();
|
||
initSmoothScroll();
|
||
initHeaderScroll();
|
||
initActiveNav();
|
||
initRevealAnimations();
|
||
initCounters();
|
||
initBackToTop();
|
||
initContactForm();
|
||
initFooterYear();
|
||
});
|
||
|
||
/* ==================== Mobile Menu ==================== */
|
||
function initMobileMenu() {
|
||
var btn = document.getElementById('mobile-menu-btn');
|
||
var menu = document.getElementById('mobile-menu');
|
||
if (!btn || !menu) return;
|
||
|
||
btn.addEventListener('click', function () {
|
||
menu.classList.toggle('hidden');
|
||
var icon = btn.querySelector('i');
|
||
if (menu.classList.contains('hidden')) {
|
||
icon.className = 'fas fa-bars text-xl';
|
||
} else {
|
||
icon.className = 'fas fa-xmark text-xl';
|
||
}
|
||
});
|
||
|
||
// Close mobile menu when a link is clicked
|
||
var links = menu.querySelectorAll('.mobile-nav-link');
|
||
links.forEach(function (link) {
|
||
link.addEventListener('click', function () {
|
||
menu.classList.add('hidden');
|
||
btn.querySelector('i').className = 'fas fa-bars text-xl';
|
||
});
|
||
});
|
||
}
|
||
|
||
/* ==================== Smooth Scroll ==================== */
|
||
function initSmoothScroll() {
|
||
var links = document.querySelectorAll('a[href^="#"]');
|
||
links.forEach(function (link) {
|
||
link.addEventListener('click', function (e) {
|
||
var href = link.getAttribute('href');
|
||
if (href === '#' || href === '') return;
|
||
var target = document.querySelector(href);
|
||
if (!target) return;
|
||
e.preventDefault();
|
||
var headerHeight = document.getElementById('header').offsetHeight;
|
||
var targetPos = target.getBoundingClientRect().top + window.pageYOffset - headerHeight + 1;
|
||
window.scrollTo({
|
||
top: targetPos,
|
||
behavior: 'smooth'
|
||
});
|
||
});
|
||
});
|
||
}
|
||
|
||
/* ==================== Header Scroll Effect ==================== */
|
||
function initHeaderScroll() {
|
||
var header = document.getElementById('header');
|
||
if (!header) return;
|
||
window.addEventListener('scroll', function () {
|
||
if (window.scrollY > 10) {
|
||
header.classList.add('scrolled');
|
||
} else {
|
||
header.classList.remove('scrolled');
|
||
}
|
||
});
|
||
}
|
||
|
||
/* ==================== Active Nav Highlighting ==================== */
|
||
function initActiveNav() {
|
||
var sections = document.querySelectorAll('section[id]');
|
||
var navLinks = document.querySelectorAll('.nav-link');
|
||
if (!sections.length || !navLinks.length) return;
|
||
|
||
var observer = new IntersectionObserver(function (entries) {
|
||
entries.forEach(function (entry) {
|
||
if (entry.isIntersecting) {
|
||
var id = entry.target.getAttribute('id');
|
||
navLinks.forEach(function (link) {
|
||
if (link.getAttribute('href') === '#' + id) {
|
||
link.classList.add('active');
|
||
link.classList.remove('text-gray-600');
|
||
} else {
|
||
link.classList.remove('active');
|
||
link.classList.add('text-gray-600');
|
||
}
|
||
});
|
||
}
|
||
});
|
||
}, {
|
||
rootMargin: '-40% 0px -55% 0px'
|
||
});
|
||
|
||
sections.forEach(function (section) {
|
||
observer.observe(section);
|
||
});
|
||
}
|
||
|
||
/* ==================== Reveal Animations ==================== */
|
||
function initRevealAnimations() {
|
||
var elements = document.querySelectorAll('.reveal-up, .reveal-left, .reveal-right');
|
||
if (!elements.length) return;
|
||
|
||
// Set animation delay from inline style
|
||
elements.forEach(function (el) {
|
||
var styleDelay = el.style.animationDelay;
|
||
if (styleDelay) {
|
||
el.style.setProperty('--reveal-delay', styleDelay);
|
||
}
|
||
});
|
||
|
||
var observer = new IntersectionObserver(function (entries) {
|
||
entries.forEach(function (entry) {
|
||
if (entry.isIntersecting) {
|
||
entry.target.classList.add('revealed');
|
||
observer.unobserve(entry.target);
|
||
}
|
||
});
|
||
}, {
|
||
threshold: 0.15,
|
||
rootMargin: '0px 0px -50px 0px'
|
||
});
|
||
|
||
elements.forEach(function (el) {
|
||
observer.observe(el);
|
||
});
|
||
}
|
||
|
||
/* ==================== Counter Animation ==================== */
|
||
function initCounters() {
|
||
var counters = document.querySelectorAll('.counter');
|
||
if (!counters.length) return;
|
||
|
||
var observer = new IntersectionObserver(function (entries) {
|
||
entries.forEach(function (entry) {
|
||
if (entry.isIntersecting) {
|
||
animateCounter(entry.target);
|
||
observer.unobserve(entry.target);
|
||
}
|
||
});
|
||
}, {
|
||
threshold: 0.5
|
||
});
|
||
|
||
counters.forEach(function (counter) {
|
||
observer.observe(counter);
|
||
});
|
||
}
|
||
|
||
function animateCounter(el) {
|
||
var target = parseInt(el.getAttribute('data-target'), 10);
|
||
var duration = 2000;
|
||
var startTime = null;
|
||
|
||
function step(timestamp) {
|
||
if (!startTime) startTime = timestamp;
|
||
var progress = Math.min((timestamp - startTime) / duration, 1);
|
||
// Ease out cubic
|
||
var eased = 1 - Math.pow(1 - progress, 3);
|
||
var current = Math.floor(eased * target);
|
||
el.textContent = current;
|
||
if (progress < 1) {
|
||
requestAnimationFrame(step);
|
||
} else {
|
||
el.textContent = target;
|
||
}
|
||
}
|
||
|
||
requestAnimationFrame(step);
|
||
}
|
||
|
||
/* ==================== Back to Top ==================== */
|
||
function initBackToTop() {
|
||
var btn = document.getElementById('back-to-top');
|
||
if (!btn) return;
|
||
|
||
window.addEventListener('scroll', function () {
|
||
if (window.scrollY > 500) {
|
||
btn.classList.add('visible');
|
||
btn.classList.remove('opacity-0', 'invisible');
|
||
} else {
|
||
btn.classList.remove('visible');
|
||
btn.classList.add('opacity-0', 'invisible');
|
||
}
|
||
});
|
||
|
||
btn.addEventListener('click', function () {
|
||
window.scrollTo({
|
||
top: 0,
|
||
behavior: 'smooth'
|
||
});
|
||
});
|
||
}
|
||
|
||
/* ==================== Contact Form ==================== */
|
||
function initContactForm() {
|
||
var form = document.getElementById('contact-form');
|
||
if (!form) return;
|
||
|
||
var successMsg = document.getElementById('form-success');
|
||
|
||
form.addEventListener('submit', function (e) {
|
||
e.preventDefault();
|
||
|
||
// Clear previous errors
|
||
var errorMessages = form.querySelectorAll('.error-msg');
|
||
errorMessages.forEach(function (msg) { msg.classList.add('hidden'); });
|
||
var inputs = form.querySelectorAll('.form-input');
|
||
inputs.forEach(function (input) { input.classList.remove('error'); });
|
||
|
||
var isValid = true;
|
||
|
||
// Validate name
|
||
var name = document.getElementById('name');
|
||
if (!name.value.trim()) {
|
||
showError(name, 'name');
|
||
isValid = false;
|
||
}
|
||
|
||
// Validate phone (Chinese phone: 11 digits starting with 1, or landline)
|
||
var phone = document.getElementById('phone');
|
||
var phoneVal = phone.value.trim();
|
||
if (!phoneVal || !/^[\d\s\-+()]{7,20}$/.test(phoneVal)) {
|
||
showError(phone, 'phone');
|
||
isValid = false;
|
||
}
|
||
|
||
// Validate email
|
||
var email = document.getElementById('email');
|
||
var emailVal = email.value.trim();
|
||
if (!emailVal || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(emailVal)) {
|
||
showError(email, 'email');
|
||
isValid = false;
|
||
}
|
||
|
||
// Validate company
|
||
var company = document.getElementById('company');
|
||
if (!company.value.trim()) {
|
||
showError(company, 'company');
|
||
isValid = false;
|
||
}
|
||
|
||
// Validate message
|
||
var message = document.getElementById('message');
|
||
if (!message.value.trim()) {
|
||
showError(message, 'message');
|
||
isValid = false;
|
||
}
|
||
|
||
if (isValid) {
|
||
// === Submit logic ===
|
||
// 此处可对接后端API,示例:
|
||
// fetch('/api/contact', { method: 'POST', body: new FormData(form) })
|
||
// .then(res => res.json())
|
||
// .then(data => { ... })
|
||
// .catch(err => { ... });
|
||
|
||
// 模拟提交成功
|
||
form.style.display = 'none';
|
||
successMsg.classList.remove('hidden');
|
||
|
||
// 5秒后恢复表单
|
||
setTimeout(function () {
|
||
form.reset();
|
||
form.style.display = '';
|
||
successMsg.classList.add('hidden');
|
||
}, 5000);
|
||
}
|
||
});
|
||
|
||
function showError(input, fieldId) {
|
||
input.classList.add('error');
|
||
var errorMsg = input.parentElement.querySelector('.error-msg');
|
||
if (errorMsg) {
|
||
errorMsg.classList.remove('hidden');
|
||
}
|
||
}
|
||
|
||
// Clear error on input
|
||
var allInputs = form.querySelectorAll('.form-input');
|
||
allInputs.forEach(function (input) {
|
||
input.addEventListener('input', function () {
|
||
input.classList.remove('error');
|
||
var errorMsg = input.parentElement.querySelector('.error-msg');
|
||
if (errorMsg) errorMsg.classList.add('hidden');
|
||
});
|
||
});
|
||
}
|
||
|
||
/* ==================== Footer Year ==================== */
|
||
function initFooterYear() {
|
||
var yearEl = document.getElementById('current-year');
|
||
if (yearEl) {
|
||
yearEl.textContent = new Date().getFullYear();
|
||
}
|
||
}
|
||
|
||
})();
|