Private
Public Access
1
0

fix: Better animations for actions

This commit is contained in:
gauvainboiche
2026-04-01 19:32:31 +02:00
parent ddd5f6ae72
commit 19483178a4
2 changed files with 39 additions and 30 deletions

View File

@@ -845,18 +845,43 @@ const mapAnimTextByType = {
}; };
/** /**
* Triggers a spinning emoji animation at the centre of the map zone. * Spawns a floating emoji that rises one cell height above the clicked cell
* and fades in/out over 1 second.
* @param {"reveal-empty"|"reveal-planet"|"capture"} type * @param {"reveal-empty"|"reveal-planet"|"capture"} type
* @param {number} x cell grid column
* @param {number} y cell grid row
*/ */
function triggerMapAnimation(type) { function triggerMapAnimation(type, x, y) {
if (!mapAnimEl) return; const cw = SVG_W / GRID_W;
mapAnimEl.textContent = mapAnimTextByType[type] || "🔍"; const ch = SVG_H / GRID_H;
mapAnimEl.classList.remove("mapAnim--active"); const rect = canvas.getBoundingClientRect();
void mapAnimEl.offsetWidth; // force reflow to restart the animation
mapAnimEl.classList.add("mapAnim--active"); // Top-centre of the cell in screen pixels, relative to the canvas element
mapAnimEl.addEventListener("animationend", () => { const screenX = ((x * cw + cw / 2 - panX) * zoom / SVG_W) * rect.width;
mapAnimEl.classList.remove("mapAnim--active"); const screenY = ((y * ch - panY) * zoom / SVG_H) * rect.height;
}, { once: true });
// One cell height in screen pixels (travel distance)
const cellScreenH = (ch * zoom / SVG_H) * rect.height;
const fontSize = Math.max(8, (cw * zoom / SVG_W) * rect.width);
const el = document.createElement("div");
el.className = "mapAnimFloat";
el.textContent = mapAnimTextByType[type] || "🔍";
el.style.left = `${screenX}px`;
el.style.top = `${screenY}px`;
el.style.fontSize = `${fontSize}px`;
el.style.transform = "translate(-50%, 0)";
canvas.parentElement.appendChild(el);
el.animate(
[
{ opacity: 0, transform: "translate(-50%, 0)" },
{ opacity: 1, transform: `translate(-50%, -${cellScreenH * 0.2}px)`, offset: 0.2 },
{ opacity: 1, transform: `translate(-50%, -${cellScreenH * 0.8}px)`, offset: 0.8 },
{ opacity: 0, transform: `translate(-50%, -${cellScreenH}px)` },
],
{ duration: 1000, easing: "ease-out", fill: "forwards" }
).onfinish = () => el.remove();
} }
// ── Cursor ──────────────────────────────────────────────────────────────────── // ── Cursor ────────────────────────────────────────────────────────────────────
@@ -1062,7 +1087,7 @@ async function onCanvasClick(ev) {
} }
if (!res.ok) throw new Error("reveal"); if (!res.ok) throw new Error("reveal");
applyRevealPayload(await res.json()); applyRevealPayload(await res.json());
triggerMapAnimation(cells.get(key)?.hasPlanet ? "reveal-planet" : "reveal-empty"); triggerMapAnimation(cells.get(key)?.hasPlanet ? "reveal-planet" : "reveal-empty", cell.x, cell.y);
startCooldown(); startCooldown();
updateEconomyDisplay(); updateEconomyDisplay();
draw(); draw();
@@ -1124,7 +1149,7 @@ async function onCanvasClick(ev) {
teamActionsRemaining = data.teamActionsRemaining; teamActionsRemaining = data.teamActionsRemaining;
updateTeamQuotaDisplay(); updateTeamQuotaDisplay();
} }
triggerMapAnimation("capture"); triggerMapAnimation("capture", cell.x, cell.y);
hint.textContent = `🏴 Planète (${cell.x},${cell.y}) capturée !`; hint.textContent = `🏴 Planète (${cell.x},${cell.y}) capturée !`;
showLocalSelection(cell.x, cell.y); showLocalSelection(cell.x, cell.y);
updateEconomyDisplay(); updateEconomyDisplay();

View File

@@ -1299,27 +1299,11 @@ canvas {
/* ── Map action animation ─────────────────────────────────────────────────── */ /* ── Map action animation ─────────────────────────────────────────────────── */
@keyframes mapAnimPop { .mapAnimFloat {
0% { transform: translate(-50%, -50%) scale(0.1); opacity: 0; }
20% { transform: translate(-50%, -50%) scale(1.1); opacity: 1; }
80% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
100% { transform: translate(-50%, -50%) scale(1.2); opacity: 0; }
}
.mapAnim {
position: absolute; position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
font-size: 88px;
line-height: 1; line-height: 1;
pointer-events: none; pointer-events: none;
z-index: 20; z-index: 20;
display: none;
user-select: none; user-select: none;
} white-space: nowrap;
.mapAnim--active {
display: block;
animation: mapAnimPop 0.5s ease-out forwards;
} }