feat: glide-back animation on stop, full dirty-set cleanup

This commit is contained in:
2026-04-24 13:24:34 +02:00
parent 7cc57e966b
commit abe307a6ca

View File

@@ -104,28 +104,37 @@ export class GravityEngine {
stop() {
this.isRunning = false;
if (this.animationFrameId) cancelAnimationFrame(this.animationFrameId);
if (this.animationFrameId) {
cancelAnimationFrame(this.animationFrameId);
this.animationFrameId = null;
}
// Reset all children back to their normal document flow
const DURATION = 600;
// Glide each body back to its origin position.
this.bodies.forEach((body) => {
body.el.style.transform = "";
body.el.style.position = "";
body.el.style.left = "";
body.el.style.top = "";
body.el.style.width = "";
body.el.style.height = "";
body.el.style.margin = "";
});
// Reset parent containers
const containers = document.querySelectorAll(".gravity-body");
containers.forEach((container) => {
const htmlContainer = container as HTMLElement;
htmlContainer.style.width = "";
htmlContainer.style.height = "";
body.el.style.transition = `transform ${DURATION}ms cubic-bezier(0.22, 1, 0.36, 1)`;
body.el.style.transform = `translate(${body.originX}px, ${body.originY}px)`;
});
// After the transition completes, clear all inline styles from every
// element we touched so the document flow is fully restored.
const elementsToClear = [...this.dirtyElements];
this.bodies = [];
this.dirtyElements = [];
setTimeout(() => {
elementsToClear.forEach((el) => {
el.style.transform = "";
el.style.transition = "";
el.style.position = "";
el.style.left = "";
el.style.top = "";
el.style.width = "";
el.style.height = "";
el.style.margin = "";
});
}, DURATION);
}
private attachMouseEvents(body: PhysicsBody) {