diff --git a/client/app.js b/client/app.js index d1af83d..a90e19a 100644 --- a/client/app.js +++ b/client/app.js @@ -171,7 +171,10 @@ class BoardUI { setOrientation(o) { this.orient = o; this.render(); } load(fen, lastMove) { try { this.chess.load(fen); } catch {} + const prev = this.lastMove; this.lastMove = lastMove || null; + // flag a genuinely new move so render() can pulse the destination square + this._pulse = !!(this.lastMove && (!prev || prev.from !== this.lastMove.from || prev.to !== this.lastMove.to)); this.selected = null; this.render(); } @@ -195,6 +198,7 @@ class BoardUI { const dark = (FILES.indexOf(file) + rank) % 2 === 0; const cell = el(`
`); if (this.lastMove && (sq === this.lastMove.from || sq === this.lastMove.to)) cell.classList.add('last'); + if (this.lastMove && sq === this.lastMove.to) { cell.classList.add('lastto'); if (this._pulse) cell.classList.add('pulse'); } if (sq === this.selected) cell.classList.add('sel'); if (sq === kingSq) cell.classList.add('check'); @@ -211,8 +215,41 @@ class BoardUI { if (legalTo.has(sq)) cell.appendChild(el(``)); board.appendChild(cell); }); + this._drawLastArrow(); + this._pulse = false; if (this.pendingPromo) this._renderPromo(); } + // column/row (0..7) of a square in the CURRENT board orientation + _cellPos(sq) { + const f = FILES.indexOf(sq[0]); + const r = +sq[1]; + return this.orient === 'w' + ? { col: f, row: 8 - r } + : { col: 7 - f, row: r - 1 }; + } + // draw a lichess-style arrow from the last move's origin to its destination + _drawLastArrow() { + const m = this.lastMove; + if (!m || !m.from || !m.to) return; + const a = this._cellPos(m.from), b = this._cellPos(m.to); + const x1 = a.col + 0.5, y1 = a.row + 0.5; + const x2 = b.col + 0.5, y2 = b.row + 0.5; + const dx = x2 - x1, dy = y2 - y1; + const len = Math.hypot(dx, dy) || 1; + const ux = dx / len, uy = dy / len; + const head = 0.42; // arrowhead length (in square units) + const start = 0.34; // pull the tail out from the piece center + const sx = x1 + ux * start, sy = y1 + uy * start; + const tipX = x2 - ux * 0.06, tipY = y2 - uy * 0.06; + const baseX = tipX - ux * head, baseY = tipY - uy * head; + const px = -uy, py = ux; // perpendicular + const hw = 0.24; // half-width of arrowhead base + const svg = el(``); + svg.innerHTML = + `