1
Fork 0
mirror of https://github.com/RGBCube/Site synced 2025-07-29 12:07:47 +00:00

cube: preserve state across pages

This commit is contained in:
RGBCube 2025-06-04 01:50:47 +03:00
parent b13bff471f
commit a6f7c93d62
Signed by: RGBCube
SSH key fingerprint: SHA256:CzqbPcfwt+GxFYNnFVCqoN5Itn4YFrshg1TrnACpA5M
4 changed files with 59 additions and 14 deletions

2
.gitignore vendored
View file

@ -3,7 +3,7 @@
!.gitignore
!site/
!site/**/
!site/**/
!*.nu

View file

@ -120,16 +120,28 @@
// 15 seconds.
const screensaverTimeoutMs = 15 * 1000;
// 10 minutes.
const stateDeleteTimeoutMs = 10 * 60 * 1000;
const lastSave = JSON.parse(localStorage.getItem("lastSave"));
if (!lastSave || Date.now() - lastSave > stateDeleteTimeoutMs) {
localStorage.removeItem("mouseDown");
localStorage.removeItem("mouseLastMove");
localStorage.removeItem("mousePrevious");
localStorage.removeItem("cubeOrient");
localStorage.removeItem("velocity");
localStorage.removeItem("impulseThisFrame");
}
const mouse = {
down: false,
lastMove: -screensaverTimeoutMs,
previous: Vec.ZERO,
};
down: JSON.parse(localStorage.getItem("mouseDown")) ?? false,
lastMove: JSON.parse(localStorage.getItem("mouseLastMove")) ?? -screensaverTimeoutMs,
previous: Vec(...JSON.parse(localStorage.getItem("mousePrevious")) ?? [0, 0, 0, 1]),
};
const orient = {
elements: document.querySelectorAll("cube-itself"),
quat: Quat(0, 0, 0, 1),
quat: Quat(...JSON.parse(localStorage.getItem("cubeOrient")) ?? [0, 0, 0, 1]),
set(q) {
this.quat = q;
@ -145,9 +157,41 @@
},
};
let velocity = Vec.ZERO;
let impulseThisFrame = Vec.ZERO;
let impulseIdle = Vec(2, 2, -2);
let velocity = Vec(...JSON.parse(localStorage.getItem("velocity")) ?? [0, 0, 0]);
let impulseThisFrame = Vec(...JSON.parse(localStorage.getItem("impulseThisFrame")) ?? [0, 0, 0]);
window.addEventListener("beforeunload", () => {
localStorage.setItem("mouseDown", JSON.stringify(mouse.down));
localStorage.setItem("mouseLastMove", JSON.stringify(-(window.performance.now() - mouse.lastMove)));
localStorage.setItem("mousePrevious", JSON.stringify([
mouse.previous.x,
mouse.previous.y,
mouse.previous.z,
mouse.previous.w,
]));
localStorage.setItem("cubeOrient", JSON.stringify([
orient.quat.x,
orient.quat.y,
orient.quat.z,
orient.quat.w,
]));
localStorage.setItem("velocity", JSON.stringify([
velocity.x,
velocity.y,
velocity.z,
]));
localStorage.setItem("impulseThisFrame", JSON.stringify([
impulseThisFrame.x,
impulseThisFrame.y,
impulseThisFrame.z,
]));
localStorage.setItem("lastSave", JSON.stringify(Date.now()));
});
const handleUp = () => {
mouse.down = false;
@ -261,6 +305,7 @@
}
if (globalThis.performance.now() - mouse.lastMove > screensaverTimeoutMs) {
const impulseIdle = Vec(2, 2, -2);
velocity = velocity.sum(impulseIdle.scale(effectiveDelta));
}

View file

@ -37,9 +37,9 @@ layout: default.vto
Copyright © {{ Temporal.Now.plainDateISO().year }}
<a draggable="false" class="flex items-center pl-2" href="/" alt="RGBCube">
{{ set cube_size = "0.75rem" }}
{{ set cube_size = "0.75rem" }}
{{ set cube_small = true }}
{{ set cube_last = true }}
{{ set cube_last = true }}
{{ include "rgbcube.vto" }}
</a>
</footer>

View file

@ -162,12 +162,12 @@ Blog Articles
context.shadowColor = "#94f475";
context.textBaseline = "top";
context.textAlign = "center";
for (const strip of strips) {
context.font = `${strip.size}px sans`;
if (strip.y > canvas.height + (strip.size * 40)) {
Object.assign(strip, randomStrip())
Object.assign(strip, randomStrip());
}
let { y: yCopy } = strip;
@ -192,7 +192,7 @@ Blog Articles
strip.y += strip.deltaY;
}
data.animationFrameId = requestAnimationFrame(animate);
};