136 lines
3.5 KiB
JavaScript
136 lines
3.5 KiB
JavaScript
const BOX_SIDE = 80;
|
|
const INDEX_MARGIN = BOX_SIDE / 2;
|
|
const INDEX_LETTERS = 'abcdefgh';
|
|
|
|
function createCanvas() {
|
|
let canvas = document.createElement('canvas');
|
|
let boardSide = BOX_SIDE * 8 + INDEX_MARGIN;
|
|
canvas.width = boardSide;
|
|
canvas.height = boardSide;
|
|
document.body.appendChild(canvas);
|
|
return canvas
|
|
}
|
|
|
|
function drawChessBoard(canvas) {
|
|
let ctx = canvas.getContext('2d');
|
|
|
|
// Draw squares
|
|
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);
|
|
}
|
|
}
|
|
|
|
function computeScreenCoords(position, canvas) {
|
|
let canvasRect = canvas.getBoundingClientRect();
|
|
let rc = boardIndexToRowCol(position);
|
|
let topPx = canvasRect.top + INDEX_MARGIN + rc[0]*BOX_SIDE + window.pageYOffset;
|
|
let leftPx = canvasRect.left + INDEX_MARGIN + rc[1]*BOX_SIDE + window.pageXOffset;
|
|
return [topPx, leftPx]
|
|
}
|
|
|
|
|
|
class Piece {
|
|
constructor(who, color, position) {
|
|
this.who = who;
|
|
this.color = color;
|
|
this.position = position;
|
|
this._im = null;
|
|
}
|
|
icon() {
|
|
return `./icons/${this.who}_${this.color}.svg`
|
|
}
|
|
draw(canvas) {
|
|
let [topPx, leftPx] = computeScreenCoords(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`;
|
|
}
|
|
}
|
|
}
|
|
|
|
class Configuration {
|
|
constructor(pieces) {
|
|
this.pieces = pieces
|
|
}
|
|
draw(canvas) {
|
|
for (let piece of this.pieces) {
|
|
piece.draw(canvas);
|
|
}
|
|
}
|
|
}
|
|
|
|
function setupBoard() {
|
|
let pawns = [];
|
|
for (let x of INDEX_LETTERS) {
|
|
pawns.push(new Piece('pawn', 'black', `${x}7`),
|
|
new Piece('pawn', 'white', `${x}2`));
|
|
}
|
|
return new Configuration([
|
|
new Piece('rook', 'black', 'a8'),
|
|
new Piece('rook', 'black', 'h8'),
|
|
new Piece('knight', 'black', 'b8'),
|
|
new Piece('knight', 'black', 'g8'),
|
|
new Piece('bishop', 'black', 'c8'),
|
|
new Piece('bishop', 'black', 'f8'),
|
|
new Piece('queen', 'black', 'd8'),
|
|
new Piece('king', 'black', 'e8'),
|
|
|
|
...pawns,
|
|
|
|
new Piece('rook', 'white', 'a1'),
|
|
new Piece('rook', 'white', 'h1'),
|
|
new Piece('knight', 'white', 'b1'),
|
|
new Piece('knight', 'white', 'g1'),
|
|
new Piece('bishop', 'white', 'c1'),
|
|
new Piece('bishop', 'white', 'f1'),
|
|
new Piece('queen', 'white', 'd1'),
|
|
new Piece('king', 'white', 'e1'),
|
|
])
|
|
}
|
|
|
|
function boardIndexToRowCol(boardIndex) {
|
|
let colLetter = boardIndex[0];
|
|
let rowDigit = boardIndex[1];
|
|
let row = 8 - parseInt(rowDigit);
|
|
let col = INDEX_LETTERS.indexOf(colLetter);
|
|
return [row, col];
|
|
}
|
|
|
|
function demo() {
|
|
let canvas = createCanvas();
|
|
drawChessBoard(canvas);
|
|
let config = setupBoard();
|
|
config.draw(canvas);
|
|
}
|
|
|
|
demo();
|