mirror of
https://github.com/Vb-Lg/class-history-template.git
synced 2026-11-03 18:46:40 +00:00
feat: initial class history template
This commit is contained in:
commit
92fa0f8f37
33 files changed
+10714
No files matched your search
@@ -0,0 +1,85 @@
|
||||
/* ================= 星空背景 ================= */
|
||||
(function () {
|
||||
const canvas = document.getElementById('stars');
|
||||
const ctx = canvas.getContext('2d');
|
||||
let w, h, stars = [], dpr = Math.min(window.devicePixelRatio || 1, 2);
|
||||
|
||||
function resize() {
|
||||
w = canvas.width = window.innerWidth * dpr;
|
||||
h = canvas.height = window.innerHeight * dpr;
|
||||
canvas.style.width = window.innerWidth + 'px';
|
||||
canvas.style.height = window.innerHeight + 'px';
|
||||
const count = Math.min(160, Math.floor(window.innerWidth / 9));
|
||||
stars = Array.from({ length: count }, () => ({
|
||||
x: Math.random() * w,
|
||||
y: Math.random() * h,
|
||||
r: (Math.random() * 1.4 + .3) * dpr,
|
||||
a: Math.random() * .6 + .15,
|
||||
s: Math.random() * .0009 + .0003,
|
||||
dy: Math.random() * .05 + .015
|
||||
}));
|
||||
}
|
||||
|
||||
let t = 0;
|
||||
function draw() {
|
||||
ctx.clearRect(0, 0, w, h);
|
||||
t += 1;
|
||||
for (const s of stars) {
|
||||
const alpha = s.a + Math.sin(t * s.s * 12) * .25;
|
||||
ctx.beginPath();
|
||||
ctx.arc(s.x, s.y, s.r, 0, Math.PI * 2);
|
||||
ctx.fillStyle = 'rgba(255,244,214,' + Math.max(0.03, Math.min(1, alpha)) + ')';
|
||||
ctx.fill();
|
||||
s.y += s.dy * dpr;
|
||||
if (s.y > h + 5) { s.y = -5; s.x = Math.random() * w; }
|
||||
}
|
||||
requestAnimationFrame(draw);
|
||||
}
|
||||
|
||||
resize();
|
||||
window.addEventListener('resize', resize);
|
||||
draw();
|
||||
})();
|
||||
|
||||
/* ================= 滚动出现 ================= */
|
||||
(function () {
|
||||
const els = document.querySelectorAll('.reveal');
|
||||
if (!('IntersectionObserver' in window)) {
|
||||
els.forEach(e => e.classList.add('visible'));
|
||||
return;
|
||||
}
|
||||
const STEP = 70; // 同一批元素之间每级错峰延时
|
||||
const MAX_STEP = 6; // 最多累加到第 6 级,再多就保持同一延时
|
||||
const io = new IntersectionObserver((entries) => {
|
||||
entries.forEach(entry => {
|
||||
if (entry.isIntersecting) {
|
||||
const el = entry.target;
|
||||
// 延时只在这里算一次,且必须随「当前文档顺序」单调不减:
|
||||
// 用 idx % 6 会让第 7 个元素的延时回到 0,比第 6 个更先出现。
|
||||
// 歌单会先按当天顺序重排 DOM(music-shuffle.js),所以这里读到的
|
||||
// 位置就是访客看到的位置,入场顺序与列表顺序一致。
|
||||
const idx = Array.from(el.parentElement.children).indexOf(el);
|
||||
const delay = Math.min(idx, MAX_STEP) * STEP;
|
||||
setTimeout(() => el.classList.add('visible'), delay);
|
||||
io.unobserve(el);
|
||||
}
|
||||
});
|
||||
}, { threshold: .1, rootMargin: '0px 0px -60px 0px' });
|
||||
els.forEach(e => io.observe(e));
|
||||
})();
|
||||
|
||||
/* ================= 进度条 + 回顶部 ================= */
|
||||
(function () {
|
||||
const bar = document.getElementById('progress');
|
||||
const top = document.getElementById('top');
|
||||
if (!bar && !top) return;
|
||||
function onScroll() {
|
||||
const st = window.scrollY || document.documentElement.scrollTop;
|
||||
const max = document.documentElement.scrollHeight - window.innerHeight;
|
||||
if (bar) bar.style.width = (max > 0 ? (st / max) * 100 : 0) + '%';
|
||||
if (top) top.classList.toggle('show', st > 500);
|
||||
}
|
||||
window.addEventListener('scroll', onScroll, { passive: true });
|
||||
onScroll();
|
||||
if (top) top.addEventListener('click', () => window.scrollTo({ top: 0, behavior: 'smooth' }));
|
||||
})();
|
||||
Reference in new issue
Block a user