103 lines
3.9 KiB
JavaScript
103 lines
3.9 KiB
JavaScript
/* 东燊科技 Donsen — 交互脚本 */
|
|||
|
|
(function () {
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
/* ---------- 语言切换(默认中文,记忆选择) ---------- */
|
||
|
|
var body = document.body;
|
||
|
|
var toggle = document.getElementById('langToggle');
|
||
|
|
var optZh = document.querySelector('.lang-zh');
|
||
|
|
var optEn = document.querySelector('.lang-en');
|
||
|
|
|
||
|
|
function applyLang(lang) {
|
||
|
|
body.setAttribute('data-lang', lang);
|
||
|
|
document.documentElement.setAttribute('lang', lang === 'zh' ? 'zh-CN' : 'en');
|
||
|
|
if (optZh) optZh.classList.toggle('is-active', lang === 'zh');
|
||
|
|
if (optEn) optEn.classList.toggle('is-active', lang === 'en');
|
||
|
|
try { localStorage.setItem('donsen-lang', lang); } catch (e) {}
|
||
|
|
}
|
||
|
|
|
||
|
|
var params = new URLSearchParams(location.search);
|
||
|
|
var saved = null;
|
||
|
|
try { saved = params.get('lang') || localStorage.getItem('donsen-lang'); } catch (e) {}
|
||
|
|
applyLang(saved === 'en' ? 'en' : 'zh');
|
||
|
|
|
||
|
|
if (toggle) {
|
||
|
|
toggle.addEventListener('click', function () {
|
||
|
|
applyLang(body.getAttribute('data-lang') === 'zh' ? 'en' : 'zh');
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------- 移动端菜单 ---------- */
|
||
|
|
var burger = document.getElementById('navBurger');
|
||
|
|
var links = document.getElementById('navLinks');
|
||
|
|
if (burger && links) {
|
||
|
|
burger.addEventListener('click', function () {
|
||
|
|
links.classList.toggle('open');
|
||
|
|
});
|
||
|
|
links.querySelectorAll('a').forEach(function (a) {
|
||
|
|
a.addEventListener('click', function () { links.classList.remove('open'); });
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------- 滚动高亮导航(rAF 节流 + offsetTop 缓存,滚动帧内零强制布局) ---------- */
|
||
|
|
var navEl = document.getElementById('nav');
|
||
|
|
var sections = Array.prototype.slice.call(document.querySelectorAll('section[id]'));
|
||
|
|
var navLinks = Array.prototype.slice.call(document.querySelectorAll('.nav-link'));
|
||
|
|
var sectionTops = [];
|
||
|
|
function measureTops() {
|
||
|
|
sectionTops = sections.map(function (s) { return s.getBoundingClientRect().top + window.scrollY; });
|
||
|
|
}
|
||
|
|
var scrollTick = false;
|
||
|
|
function onScrollFrame() {
|
||
|
|
scrollTick = false;
|
||
|
|
var y = window.scrollY;
|
||
|
|
var scrolled = y > 40;
|
||
|
|
if (navEl) {
|
||
|
|
navEl.style.background = scrolled ? 'rgba(6,15,34,.96)' : 'rgba(6,15,34,.82)';
|
||
|
|
// 滚动后切纯色背景并去掉毛玻璃(backdrop-filter 持续混合开销大)
|
||
|
|
navEl.classList.toggle('scrolled', scrolled);
|
||
|
|
}
|
||
|
|
var current = sections[0] ? sections[0].id : '';
|
||
|
|
for (var i = 0; i < sectionTops.length; i++) {
|
||
|
|
if (sectionTops[i] <= y + 120) current = sections[i].id;
|
||
|
|
}
|
||
|
|
navLinks.forEach(function (l) {
|
||
|
|
l.classList.toggle('active', l.getAttribute('href') === '#' + current);
|
||
|
|
});
|
||
|
|
}
|
||
|
|
function onScroll() {
|
||
|
|
if (scrollTick) return;
|
||
|
|
scrollTick = true;
|
||
|
|
requestAnimationFrame(onScrollFrame);
|
||
|
|
}
|
||
|
|
measureTops();
|
||
|
|
window.addEventListener('scroll', onScroll, { passive: true });
|
||
|
|
window.addEventListener('resize', function () { measureTops(); onScrollFrame(); });
|
||
|
|
onScrollFrame();
|
||
|
|
|
||
|
|
/* ---------- 滚动显现动画(?static=1 或减弱动效时直接全展) ---------- */
|
||
|
|
var revealEls = document.querySelectorAll('.reveal');
|
||
|
|
var staticMode = new URLSearchParams(location.search).get('static') === '1';
|
||
|
|
var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||
|
|
if (staticMode || reduceMotion || !('IntersectionObserver' in window)) {
|
||
|
|
revealEls.forEach(function (el) { el.classList.add('in'); });
|
||
|
|
} else {
|
||
|
|
var io = new IntersectionObserver(function (entries) {
|
||
|
|
entries.forEach(function (en) {
|
||
|
|
if (en.isIntersecting) {
|
||
|
|
en.target.classList.add('in');
|
||
|
|
io.unobserve(en.target);
|
||
|
|
}
|
||
|
|
});
|
||
|
|
}, { threshold: 0.12 });
|
||
|
|
revealEls.forEach(function (el) { io.observe(el); });
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------- 页脚年份 ---------- */
|
||
|
|
var y = new Date().getFullYear();
|
||
|
|
['year', 'year-en'].forEach(function (id) {
|
||
|
|
var el = document.getElementById(id);
|
||
|
|
if (el) el.textContent = y;
|
||
|
|
});
|
||
|
|
})();
|