This commit is contained in:
Maciej Caderek
2022-01-17 04:54:19 +01:00
parent 7052c74171
commit 9482b11319
16 changed files with 140 additions and 86 deletions

View File

@@ -13,20 +13,23 @@ class Board {
private flipped: boolean = false;
private boardData: BoardData | null = null;
private ctx: CanvasRenderingContext2D;
private tempCtx: CanvasRenderingContext2D;
private borderVisible: boolean = true;
private lastMove: Move | null = null;
public canvas: HTMLCanvasElement = document.createElement("canvas");
private tempCanvas: HTMLCanvasElement = document.createElement("canvas");
constructor(private tiles: number = 8) {
this.canvas;
const ctx = this.canvas.getContext("2d");
const tempCtx = this.tempCanvas.getContext("2d");
this.canvas.classList.add("board");
if (ctx == null) {
if (ctx === null || tempCtx === null) {
throw new Error("Cannot create canvas 2D context");
}
this.ctx = ctx;
this.tempCtx = tempCtx;
this.setSize(this.size);
}
@@ -34,6 +37,8 @@ class Board {
this.size = size;
this.canvas.width = size;
this.canvas.height = size;
this.tempCanvas.width = size;
this.tempCanvas.height = size;
return this;
}
@@ -86,6 +91,13 @@ class Board {
return color === "w" ? "b" : "w";
}
async renderTitleScreen(header: { [key: string]: string | undefined }) {
this.tempCtx.clearRect(0, 0, this.size, this.size);
await drawSquare(this.tempCtx, this.size, 0, 0, this.style.border);
this.ctx.drawImage(this.tempCanvas, 0, 0);
}
async render(boardData: BoardData | null, move: Move | null = null) {
this.lastMove = move;
this.boardData = boardData;
@@ -106,13 +118,19 @@ class Board {
? this.getOppositeColor(move?.color)
: undefined;
this.ctx.clearRect(0, 0, this.size, this.size);
this.tempCtx.clearRect(0, 0, this.size, this.size);
await drawSquare(this.ctx, innerSize, borderWidth, borderWidth, background);
await drawSquare(
this.tempCtx,
innerSize,
borderWidth,
borderWidth,
background
);
if (hasBorder) {
await drawBorder(
this.ctx,
this.tempCtx,
this.size - borderWidth,
borderWidth / 2,
borderWidth / 2,
@@ -132,12 +150,12 @@ class Board {
const x = file * squareSize + borderWidth;
const y = rank * squareSize + borderWidth;
await drawSquare(this.ctx, squareSize, x, y, style);
await drawSquare(this.tempCtx, squareSize, x, y, style);
}
}
drawCoords(
this.ctx,
this.tempCtx,
coords,
squareSize,
this.tiles,
@@ -149,10 +167,10 @@ class Board {
if (boardData !== null) {
if (this.lastMove) {
drawMoveIndicators(
this.ctx,
this.tempCtx,
this.lastMove,
squareSize,
moveIndicator,
this.style,
borderWidth,
this.tiles,
this.flipped
@@ -160,7 +178,7 @@ class Board {
}
await drawPieces(
this.ctx,
this.tempCtx,
boardData,
squareSize,
borderWidth,
@@ -171,6 +189,9 @@ class Board {
true
);
}
this.ctx.clearRect(0, 0, this.size, this.size);
this.ctx.drawImage(this.tempCanvas, 0, 0);
}
toImgUrl() {

View File

@@ -39,7 +39,12 @@ const drawCoords = (
ctx.font = `${fontSize}px ${FONT_FAMILY}`;
orderedRanks.forEach((v, i) => {
ctx.fillStyle = i % 2 === 0 ? coords.darkColor : coords.lightColor;
ctx.fillStyle =
borderWidth > 0
? coords.onBorder
: i % 2 === 0
? coords.onLight
: coords.onDark;
ctx.textAlign = borderWidth > 0 ? "center" : "left";
ctx.fillText(v, offsetRankX, squareSize * i + fontSize + offsetRankY);
@@ -49,7 +54,12 @@ const drawCoords = (
const orderedFiles = blackSide ? files.reverse() : files;
orderedFiles.forEach((v, i) => {
ctx.fillStyle = i % 2 === 0 ? coords.lightColor : coords.darkColor;
ctx.fillStyle =
borderWidth > 0
? coords.onBorder
: i % 2 === 0
? coords.onDark
: coords.onLight;
ctx.textAlign = borderWidth > 0 ? "center" : "left";
ctx.fillText(

View File

@@ -1,5 +1,5 @@
import { Move } from "chess.js";
import { SquareStyle } from "../../types";
import { Style, SquareStyle } from "../../types";
import drawSquare from "./drawSquare";
const FILES = "abcdefghijklmnopqrstuwvxyz";
@@ -15,18 +15,36 @@ const drawMoveIndicators = async (
ctx: CanvasRenderingContext2D,
move: Move,
squareSize: number,
squareStyle: SquareStyle,
{ dark, light, moveIndicator }: Style,
borderWidth: number,
tiles: number,
flipped: boolean = false
) => {
const [x0, y0] = notationToXY(move.from, flipped, tiles);
const [x1, y1] = notationToXY(move.to, flipped, tiles);
const [fromX, fromY, toX, toY] = [
...notationToXY(move.from, flipped, tiles),
...notationToXY(move.to, flipped, tiles),
].map((v) => v * squareSize + borderWidth);
drawSquare(ctx, squareSize, fromX, fromY, squareStyle);
drawSquare(ctx, squareSize, toX, toY, squareStyle);
let fromStyle;
let toStyle;
if (moveIndicator.type === "hueShift") {
ctx.filter = `hue-rotate(${moveIndicator.data}deg)`;
fromStyle = (x0 + y0) % 2 === 0 ? light : dark;
toStyle = (x1 + y1) % 2 === 0 ? light : dark;
} else {
fromStyle = {
type: "solid",
data: { color: moveIndicator.data },
} as SquareStyle;
toStyle = fromStyle;
}
drawSquare(ctx, squareSize, fromX, fromY, fromStyle);
drawSquare(ctx, squareSize, toX, toY, toStyle);
};
export default drawMoveIndicators;

View File

@@ -21,10 +21,8 @@ const style: Style = {
},
},
moveIndicator: {
type: "solid",
data: {
color: "#7D3EC155",
},
type: "hueShift",
data: 70,
},
border: {
type: "solid",
@@ -33,8 +31,9 @@ const style: Style = {
},
},
coords: {
lightColor: "#ececa4",
darkColor: "#ececa4",
onLight: "#72b339",
onDark: "#ececa4",
onBorder: "#ececa4",
},
};

View File

@@ -22,10 +22,8 @@ const style: Style = {
},
},
moveIndicator: {
type: "solid",
data: {
color: "#0077ff00",
},
type: "color",
data: "#ee59ff55",
},
border: {
type: "gradient",
@@ -35,8 +33,9 @@ const style: Style = {
},
},
coords: {
lightColor: "rgba(255, 255, 255, 0.9)",
darkColor: "rgba(255, 255, 255, 0.9)",
onLight: "rgba(0, 0, 0, 0.5)",
onDark: "rgba(255, 255, 255, 0.9)",
onBorder: "rgba(255, 255, 255, 0.9)",
},
};

View File

@@ -21,10 +21,8 @@ const style: Style = {
},
},
moveIndicator: {
type: "solid",
data: {
color: "#0055ff77",
},
type: "color",
data: "#00ffff55",
},
border: {
type: "solid",
@@ -33,8 +31,9 @@ const style: Style = {
},
},
coords: {
lightColor: "#222",
darkColor: "#222",
onLight: "#222",
onDark: "#ddd",
onBorder: "#ddd",
},
};

View File

@@ -2,7 +2,7 @@ import avocado from "./avocado";
import calm from "./calm";
import standard from "./standard";
import glass from "./glass";
// import kittens from "./kittens";
import kittens from "./kittens";
import lichess from "./lichess";
import lila from "./lila";
import mono from "./mono";
@@ -12,7 +12,7 @@ export default {
avocado,
calm,
glass,
// kittens,
kittens,
lichess,
lila,
mono,

View File

@@ -5,26 +5,24 @@ const style: Style = {
background: {
type: "image",
data: {
src: "https://placekitten.com/1024/1024",
src: "https://placekitten.com/720/720",
},
},
dark: {
type: "image",
type: "solid",
data: {
src: "https://placekitten.com/128/128",
color: "#00000055",
},
},
light: {
type: "solid",
data: {
color: "transparent",
color: "#ffffff55",
},
},
moveIndicator: {
type: "solid",
data: {
color: "#0055ff77",
},
type: "color",
data: "#ffff0055",
},
border: {
type: "solid",
@@ -33,8 +31,9 @@ const style: Style = {
},
},
coords: {
lightColor: "#eee",
darkColor: "#eee",
onLight: "#333",
onDark: "#eee",
onBorder: "#eee",
},
};

View File

@@ -21,21 +21,19 @@ const style: Style = {
},
},
moveIndicator: {
type: "hueShift",
data: 40,
},
border: {
type: "solid",
data: {
color: "rgba(155,199,0,0.41)",
color: "#896d56",
},
},
border: null,
// border: {
// type: "solid",
// data: {
// color: "#896d56",
// },
// },
coords: {
lightColor: "#f0d9b5",
darkColor: "#b58863",
onLight: "#b58863",
onDark: "#f0d9b5",
onBorder: "#f0d9b5",
},
};

View File

@@ -21,10 +21,8 @@ const style: Style = {
},
},
moveIndicator: {
type: "solid",
data: {
color: "#0055ff77",
},
type: "hueShift",
data: 180,
},
border: {
type: "solid",
@@ -33,8 +31,9 @@ const style: Style = {
},
},
coords: {
lightColor: "#e5d0cb",
darkColor: "#e5d0cb",
onLight: "#c0acb5",
onDark: "#e5d0cb",
onBorder: "#e5d0cb",
},
};

View File

@@ -21,10 +21,8 @@ const style: Style = {
},
},
moveIndicator: {
type: "solid",
data: {
color: "#0055ff77",
},
type: "color",
data: "#00ff0044",
},
border: {
type: "solid",
@@ -33,8 +31,9 @@ const style: Style = {
},
},
coords: {
lightColor: "#eee",
darkColor: "#eee",
onLight: "#bbb",
onDark: "#eee",
onBorder: "#eee",
},
};

View File

@@ -21,16 +21,19 @@ const style: Style = {
},
},
moveIndicator: {
type: "hueShift",
data: 330,
},
border: {
type: "solid",
data: {
// color: "#0055ff77",
color: "transparent",
color: "#962c2c",
},
},
border: null,
coords: {
lightColor: "#ffa987",
darkColor: "#e54b4b",
onLight: "#e54b4b",
onDark: "#ffa987",
onBorder: "#ffa987",
},
};

View File

@@ -21,10 +21,8 @@ const style: Style = {
},
},
moveIndicator: {
type: "solid",
data: {
color: "#0055ff55",
},
type: "color",
data: "#0088ff66",
},
border: {
type: "solid",
@@ -33,8 +31,9 @@ const style: Style = {
},
},
coords: {
lightColor: "#eee",
darkColor: "#eee",
onLight: "#999",
onDark: "#eee",
onBorder: "#eee",
},
};

View File

@@ -78,6 +78,10 @@ class Game {
return this.replay.board();
}
getHeader() {
return this.replay.header();
}
pgn() {
return this.game.pgn();
}

View File

@@ -19,6 +19,8 @@ const play = async (board: Board, pgn: string | null, interval: number) => {
}
// game.goto(28);
// await board.renderTitleScreen(game.getHeader());
// await delay(interval);
await board.render(game.getBoardData());
while (true) {
@@ -46,16 +48,16 @@ const createDownloadLink = async (pgn: string, style: Style) => {
};
const main = async () => {
const style = styles.avocado;
const style = styles.calm;
const hash = window.location.hash;
const pgn = hash === "" ? null : decompressPGN(hash.slice(1));
const board = new Board(8).setStyle(style).setSize(720).showBorder();
window.location.hash = "#alala";
$app?.appendChild(board.canvas);
console.log(pgn);
play(board, pgn, 1000);
// createDownloadLink(pgns[0], style).then((link) => {

View File

@@ -33,19 +33,24 @@ export type Image = {
};
export type Coords = {
darkColor: string;
lightColor: string;
onLight: string;
onDark: string;
onBorder: string;
};
export type SquareStyle = Gradient | Solid | Image;
export type MoveIndicator =
| { type: "hueShift"; data: number }
| { type: "color"; data: string };
export type Style = {
name: string;
background: SquareStyle;
light: SquareStyle;
dark: SquareStyle;
moveIndicator: SquareStyle;
border: SquareStyle | null;
moveIndicator: MoveIndicator;
border: SquareStyle;
coords: Coords;
};