fix: Better animations for actions
This commit is contained in:
@@ -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 {number} x cell grid column
|
||||
* @param {number} y cell grid row
|
||||
*/
|
||||
function triggerMapAnimation(type) {
|
||||
if (!mapAnimEl) return;
|
||||
mapAnimEl.textContent = mapAnimTextByType[type] || "🔍";
|
||||
mapAnimEl.classList.remove("mapAnim--active");
|
||||
void mapAnimEl.offsetWidth; // force reflow to restart the animation
|
||||
mapAnimEl.classList.add("mapAnim--active");
|
||||
mapAnimEl.addEventListener("animationend", () => {
|
||||
mapAnimEl.classList.remove("mapAnim--active");
|
||||
}, { once: true });
|
||||
function triggerMapAnimation(type, x, y) {
|
||||
const cw = SVG_W / GRID_W;
|
||||
const ch = SVG_H / GRID_H;
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
|
||||
// Top-centre of the cell in screen pixels, relative to the canvas element
|
||||
const screenX = ((x * cw + cw / 2 - panX) * zoom / SVG_W) * rect.width;
|
||||
const screenY = ((y * ch - panY) * zoom / SVG_H) * rect.height;
|
||||
|
||||
// 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 ────────────────────────────────────────────────────────────────────
|
||||
@@ -1062,7 +1087,7 @@ async function onCanvasClick(ev) {
|
||||
}
|
||||
if (!res.ok) throw new Error("reveal");
|
||||
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();
|
||||
updateEconomyDisplay();
|
||||
draw();
|
||||
@@ -1124,7 +1149,7 @@ async function onCanvasClick(ev) {
|
||||
teamActionsRemaining = data.teamActionsRemaining;
|
||||
updateTeamQuotaDisplay();
|
||||
}
|
||||
triggerMapAnimation("capture");
|
||||
triggerMapAnimation("capture", cell.x, cell.y);
|
||||
hint.textContent = `🏴 Planète (${cell.x},${cell.y}) capturée !`;
|
||||
showLocalSelection(cell.x, cell.y);
|
||||
updateEconomyDisplay();
|
||||
|
||||
@@ -1299,27 +1299,11 @@ canvas {
|
||||
|
||||
/* ── Map action animation ─────────────────────────────────────────────────── */
|
||||
|
||||
@keyframes mapAnimPop {
|
||||
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 {
|
||||
.mapAnimFloat {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
font-size: 88px;
|
||||
line-height: 1;
|
||||
pointer-events: none;
|
||||
z-index: 20;
|
||||
display: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.mapAnim--active {
|
||||
display: block;
|
||||
animation: mapAnimPop 0.5s ease-out forwards;
|
||||
white-space: nowrap;
|
||||
}
|
||||
Reference in New Issue
Block a user