const BOX_SIDE = 80; const INDEX_MARGIN = BOX_SIDE / 2; const INDEX_LETTERS = 'abcdefgh'; export class Canvas { constructor() { this._canvas = document.createElement('canvas'); let boardSide = BOX_SIDE * 8 + INDEX_MARGIN; this._canvas.width = boardSide; this._canvas.height = boardSide; document.body.appendChild(this._canvas); this.drawChessBoard(); } drawChessBoard() { // Draw squares let ctx = this._canvas.getContext('2d'); ctx.fillStyle = '#c0c0c0'; for (let r = 0; r < 8; r++) { for (let c = 0; c < 8; c++) { if ((r + c) % 2) ctx.fillRect(c * BOX_SIDE + INDEX_MARGIN, r * BOX_SIDE + INDEX_MARGIN, BOX_SIDE, BOX_SIDE); } } // Draw letters ctx.fillStyle = 'black'; let fontsize = INDEX_MARGIN / 2; ctx.font = `${fontsize}px Monospace`; for (let idx = 0; idx < 8; idx++) { ctx.fillText(INDEX_LETTERS[idx], BOX_SIDE * idx + BOX_SIDE / 2 + INDEX_MARGIN - fontsize / 4, INDEX_MARGIN / 2); ctx.fillText((8 - idx).toString(), INDEX_MARGIN / 2 - fontsize / 4, BOX_SIDE * idx + BOX_SIDE / 2 + INDEX_MARGIN + fontsize / 4); } } screenCoordsToRowCol(cx, cy) { let canvasRect = this._canvas.getBoundingClientRect(); if (cx > canvasRect.right || cy > canvasRect.bottom) { return null; } let canvasX = cx - canvasRect.left; let canvasY = cy - canvasRect.top; let row = Math.floor((canvasY - INDEX_MARGIN) / BOX_SIDE); let col = Math.floor((canvasX - INDEX_MARGIN) / BOX_SIDE); return [row, col]; } rowColToScreenCoords(row, col) { let canvasRect = this._canvas.getBoundingClientRect(); let topPx = canvasRect.top + INDEX_MARGIN + row * BOX_SIDE + window.pageYOffset; let leftPx = canvasRect.left + INDEX_MARGIN + col * BOX_SIDE + window.pageXOffset; return [topPx, leftPx] } } function boardIndexToRowCol(boardIndex) { let [colLetter, rowDigit] = boardIndex; let row = 8 - parseInt(rowDigit); let col = INDEX_LETTERS.indexOf(colLetter); return [row, col]; } export function rowColToBoardIndex(row, col) { let rowDigit = 8 - row; let colLetter = INDEX_LETTERS[col]; return `${colLetter}${rowDigit}`; } export class PieceVis { constructor(piece) { this.icon = `./icons/${piece.who}_${piece.color}.svg`; this.position = piece.position; this.im = null; } draw(canvas) { let [topPx, leftPx] = canvas.rowColToScreenCoords( ...boardIndexToRowCol(this.position), canvas ); if (this.im === null) { let im = new Image(BOX_SIDE, BOX_SIDE); im.src = this.icon; im.onload = () => { im.style.position = 'absolute'; im.style.top = `${topPx}px`; im.style.left = `${leftPx}px`; }; document.body.appendChild(im); this.im = im; } else { this.im.style.top = `${topPx}px`; this.im.style.left = `${leftPx}px`; } } undraw() { if (this.im !== null) { this.im.remove(); this.im = null; } } } export class ConfigVis { constructor(configuration) { this.configuration = configuration; this.piecesVis = new Map(); } draw(canvas) { for (const piece of this.configuration) { let pieceVis = new PieceVis(piece); pieceVis.draw(canvas); this.piecesVis.set(piece.position, pieceVis); } } undraw() { for (let [position, pieceVis] of this.piecesVis) { pieceVis.undraw(); } this.piecesVis.clear(); } }