76 lines
2.1 KiB
JavaScript
76 lines
2.1 KiB
JavaScript
/*
|
|
* Mountain background animation.
|
|
*
|
|
* Cycles the 60 ASCII frames from window.TP_MOUNTAIN_FRAMES at 12 fps.
|
|
* Mounts a single <pre> in the body that gets its textContent swapped
|
|
* on each frame. Uses requestAnimationFrame to stay smooth and yields
|
|
* cleanly to the browser's frame budget. Pauses on prefers-reduced-motion
|
|
* and on document.hidden.
|
|
*/
|
|
(function () {
|
|
"use strict";
|
|
|
|
function init() {
|
|
if (typeof window.TP_MOUNTAIN_FRAMES === "undefined") return;
|
|
if (document.querySelector("[data-tp-mountain]")) return;
|
|
|
|
var pre = document.createElement("pre");
|
|
pre.className = "tp-mountain-frame";
|
|
pre.setAttribute("data-tp-mountain", "");
|
|
pre.setAttribute("aria-hidden", "true");
|
|
pre.textContent = window.TP_MOUNTAIN_FRAMES[0];
|
|
document.body.appendChild(pre);
|
|
|
|
var n = window.TP_MOUNTAIN_N_FRAMES;
|
|
var fps = window.TP_MOUNTAIN_FPS;
|
|
var i = 0;
|
|
var last = 0;
|
|
var acc = 0;
|
|
var interval = 1000 / fps;
|
|
|
|
var reduceMotion =
|
|
window.matchMedia &&
|
|
window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
|
|
if (reduceMotion) {
|
|
// Show a single representative frame; no animation.
|
|
pre.textContent = window.TP_MOUNTAIN_FRAMES[Math.floor(n / 2)];
|
|
return;
|
|
}
|
|
|
|
function step(ts) {
|
|
if (!last) last = ts;
|
|
acc += ts - last;
|
|
last = ts;
|
|
while (acc >= interval) {
|
|
i = (i + 1) % n;
|
|
pre.textContent = window.TP_MOUNTAIN_FRAMES[i];
|
|
acc -= interval;
|
|
}
|
|
if (!document.hidden) {
|
|
requestAnimationFrame(step);
|
|
} else {
|
|
// Resume on next visibility change.
|
|
document.addEventListener(
|
|
"visibilitychange",
|
|
function onVisible() {
|
|
if (!document.hidden) {
|
|
last = 0;
|
|
acc = 0;
|
|
document.removeEventListener("visibilitychange", onVisible);
|
|
requestAnimationFrame(step);
|
|
}
|
|
}
|
|
);
|
|
}
|
|
}
|
|
requestAnimationFrame(step);
|
|
}
|
|
|
|
if (document.readyState === "loading") {
|
|
document.addEventListener("DOMContentLoaded", init);
|
|
} else {
|
|
init();
|
|
}
|
|
})();
|