返回 DeepSeek-Reasonix
fx.js
根目录 / site / src / scripts / fx.js
1 // Reasonix — motion & FX layer (all effects respect data-motion + prefers-reduced-motion)
2 (function () {
3 const reduced = window.matchMedia("(prefers-reduced-motion: reduce)").matches;
4 const rich = () => document.body.dataset.motion === "rich" && !reduced;
5
6 /* spotlight border on cards */
7 document.querySelectorAll(".feat, .os-card, .doc-card").forEach((card) => {
8 card.addEventListener("mousemove", (e) => {
9 const r = card.getBoundingClientRect();
10 card.style.setProperty("--mx", e.clientX - r.left + "px");
11 card.style.setProperty("--my", e.clientY - r.top + "px");
12 });
13 });
14
15 /* stat counters (run when terminal playback finishes) */
16 const counters = Array.from(document.querySelectorAll("[data-cnt]"));
17 const fmt = (el, v) => {
18 if (el.dataset.fmt === "hm") {
19 const m = Math.round(v);
20 return Math.floor(m / 60) + "h " + (m % 60) + "m";
21 }
22 const dec = +(el.dataset.dec || 0);
23 return (el.dataset.pre || "") + v.toFixed(dec) + (el.dataset.suf || "");
24 };
25 const runCounters = () => {
26 counters.forEach((el) => {
27 const target = parseFloat(el.dataset.cnt);
28 if (!rich()) { el.textContent = fmt(el, target); return; }
29 const t0 = performance.now(), dur = 1500;
30 const frame = (t) => {
31 const p = Math.min(1, (t - t0) / dur);
32 const e = 1 - Math.pow(1 - p, 3);
33 el.textContent = fmt(el, target * e);
34 if (p < 1) requestAnimationFrame(frame);
35 };
36 requestAnimationFrame(frame);
37 });
38 };
39 document.addEventListener("rx:term-played", runCounters);
40 })();
41
41 lines JAVASCRIPT