Python/玄潮官网/js/main.js

308 lines
10 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ==================== 玄潮科技 - 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();
}
}
})();