WIP
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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)",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
@@ -78,6 +78,10 @@ class Game {
|
||||
return this.replay.board();
|
||||
}
|
||||
|
||||
getHeader() {
|
||||
return this.replay.header();
|
||||
}
|
||||
|
||||
pgn() {
|
||||
return this.game.pgn();
|
||||
}
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
13
src/types.ts
13
src/types.ts
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user