This commit is contained in:
Maciej Caderek
2022-01-20 06:45:14 +01:00
parent 918a5dff4f
commit 8733c1c3ab
18 changed files with 308 additions and 226 deletions

View File

@@ -1,11 +1,11 @@
import { Move } from "chess.js"; import { Move } from "chess.js";
import { Style, BoardData } from "../types"; import { Style, BoardData } from "../types";
import drawSquare from "./layers/drawSquare"; import drawRectangle from "./layers/drawRectangle";
import drawBorder from "./layers/drawBorder";
import drawCoords from "./layers/drawCoords"; import drawCoords from "./layers/drawCoords";
import drawMoveIndicators from "./layers/drawMoveIndicators"; import drawMoveIndicators from "./layers/drawMoveIndicators";
import drawPieces from "./layers/drawPieces"; import drawPieces from "./layers/drawPieces";
import drawHeader from "./layers/drawHeader.ts"; import drawHeader from "./layers/drawHeader.ts";
import drawExtraInfo from "./layers/drawExtraInfo";
import boards from "./styles-board"; import boards from "./styles-board";
class Board { class Board {
@@ -24,6 +24,9 @@ class Board {
private innerSize: number = 672; private innerSize: number = 672;
private borderWidth: number = 24; private borderWidth: number = 24;
private background: Promise<ImageBitmap> | null = null; private background: Promise<ImageBitmap> | null = null;
private extraInfo: boolean = true;
private scale: number = 1;
private margin: number = 0;
constructor(private tiles: number = 8) { constructor(private tiles: number = 8) {
const ctx = this.canvas.getContext("2d"); const ctx = this.canvas.getContext("2d");
@@ -41,10 +44,13 @@ class Board {
setSize(size: number) { setSize(size: number) {
this.size = size; this.size = size;
this.scale = size / 720;
this.margin = this.extraInfo ? 50 * this.scale : 0;
this.canvas.width = size; this.canvas.width = size;
this.canvas.height = size; this.canvas.height = size + this.margin * 2;
this.tempCanvas.width = size; this.tempCanvas.width = size;
this.tempCanvas.height = size; this.tempCanvas.height = size + this.margin * 2;
const tempBorderWidth = this.borderVisible ? this.size / 32 : 0; const tempBorderWidth = this.borderVisible ? this.size / 32 : 0;
const tempInnerSize = this.size - tempBorderWidth * 2; const tempInnerSize = this.size - tempBorderWidth * 2;
@@ -106,33 +112,32 @@ class Board {
return color === "w" ? "b" : "w"; return color === "w" ? "b" : "w";
} }
async renderTitleScreen(header: { [key: string]: string | undefined }) { async titleFrame(header: { [key: string]: string | undefined }) {
await drawHeader(this.tempCtx, this.size, this.style, header, this.flipped); await drawHeader(
this.ctx.drawImage(this.tempCanvas, 0, 0); this.tempCtx,
this.size,
this.scale,
this.margin,
this.style,
header,
this.flipped
);
} }
async renderBackground() { async renderBackground() {
const { background, dark, light, border, coords } = this.style; const { background, dark, light, border, coords } = this.style;
await drawSquare( await drawRectangle(this.tempCtx, this.width, this.height, 0, 0, border);
await drawRectangle(
this.tempCtx, this.tempCtx,
this.innerSize, this.innerSize,
this.innerSize,
this.borderVisible ? this.borderWidth : 0, this.borderVisible ? this.borderWidth : 0,
this.borderVisible ? this.borderWidth : 0, (this.borderVisible ? this.borderWidth : 0) + this.margin,
background background
); );
if (this.borderVisible) {
await drawBorder(
this.tempCtx,
this.size - this.borderWidth,
this.borderWidth / 2,
this.borderWidth / 2,
this.borderWidth,
border
);
}
for (let rank = 0; rank < this.tiles; rank++) { for (let rank = 0; rank < this.tiles; rank++) {
for (let file = 0; file < this.tiles; file++) { for (let file = 0; file < this.tiles; file++) {
const style = const style =
@@ -142,9 +147,16 @@ class Board {
: dark; : dark;
const x = file * this.squareSize + this.borderWidth; const x = file * this.squareSize + this.borderWidth;
const y = rank * this.squareSize + this.borderWidth; const y = rank * this.squareSize + this.borderWidth + this.margin;
await drawSquare(this.tempCtx, this.squareSize, x, y, style); await drawRectangle(
this.tempCtx,
this.squareSize,
this.squareSize,
x,
y,
style
);
} }
} }
@@ -156,13 +168,18 @@ class Board {
this.flipped, this.flipped,
this.borderWidth, this.borderWidth,
this.size, this.size,
this.borderVisible this.borderVisible,
this.margin
); );
this.background = createImageBitmap(this.tempCanvas); this.background = createImageBitmap(this.tempCanvas);
} }
async render(boardData: BoardData | null, move: Move | null = null) { async frame(
boardData: BoardData | null,
header: { [key: string]: string | undefined },
move: Move | null = null
) {
this.lastMove = move; this.lastMove = move;
this.boardData = boardData; this.boardData = boardData;
@@ -190,10 +207,13 @@ class Board {
this.style, this.style,
this.borderWidth, this.borderWidth,
this.tiles, this.tiles,
this.flipped this.flipped,
this.margin
); );
} }
const piecesShadow = false;
await drawPieces( await drawPieces(
this.tempCtx, this.tempCtx,
boardData, boardData,
@@ -203,10 +223,26 @@ class Board {
this.flipped, this.flipped,
check, check,
mate, mate,
true piecesShadow,
this.margin
);
if (this.extraInfo && header) {
await drawExtraInfo(
this.tempCtx,
this.width,
this.height,
this.scale,
this.margin,
this.style,
header,
this.flipped
); );
} }
}
}
render() {
this.ctx.clearRect(0, 0, this.size, this.size); this.ctx.clearRect(0, 0, this.size, this.size);
this.ctx.drawImage(this.tempCanvas, 0, 0); this.ctx.drawImage(this.tempCanvas, 0, 0);
} }
@@ -223,6 +259,16 @@ class Board {
img.src = dataUrl; img.src = dataUrl;
return img; return img;
} }
get width() {
return this.size;
}
get height() {
return this.size + this.margin * 2;
}
toGIF() {}
} }
export default Board; export default Board;

View File

@@ -10,16 +10,17 @@ const gradientDirs = {
const createGradient = ( const createGradient = (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
data: GradientData, data: GradientData,
size: number, width: number,
height: number,
x: number, x: number,
y: number y: number
) => { ) => {
const [dirXStart, dirYStart, dirXStop, dirYStop] = gradientDirs[data.dir]; const [dirXStart, dirYStart, dirXStop, dirYStop] = gradientDirs[data.dir];
const gradient = ctx.createLinearGradient( const gradient = ctx.createLinearGradient(
x + dirXStart * size, x + dirXStart * width,
y + dirYStart * size, y + dirYStart * height,
x + dirXStop * size, x + dirXStop * width,
y + dirYStop * size y + dirYStop * height
); );
const maxIndex = data.colors.length - 1; const maxIndex = data.colors.length - 1;

View File

@@ -1,28 +0,0 @@
import { SquareStyle } from "../../types";
import createGradient from "../fill/createGradient";
import createPattern from "../fill/createPattern";
const drawBorder = async (
ctx: CanvasRenderingContext2D,
size: number,
x: number,
y: number,
width: number,
squareStyle: SquareStyle
) => {
const fill = await (squareStyle.type === "solid"
? squareStyle.data.color
: squareStyle.type === "gradient"
? createGradient(ctx, squareStyle.data, size, x, y)
: createPattern(ctx, squareStyle.data));
if (fill === null) {
throw new Error("Cannot create canvas fill style");
}
ctx.lineWidth = width;
ctx.strokeStyle = fill;
ctx.strokeRect(x, y, size, size);
};
export default drawBorder;

View File

@@ -11,7 +11,8 @@ const drawCoords = (
blackSide: boolean = false, blackSide: boolean = false,
borderWidth: number, borderWidth: number,
size: number, size: number,
hasBorder: boolean hasBorder: boolean,
margin: number
) => { ) => {
const scale = size / 1024; const scale = size / 1024;
@@ -41,9 +42,10 @@ const drawCoords = (
: coords.onDark; : coords.onDark;
const x = hasBorder ? borderWidth / 2 : offsetA; const x = hasBorder ? borderWidth / 2 : offsetA;
const y = hasBorder const y =
(hasBorder
? squareSize * i + borderWidth + squareSize / 2 ? squareSize * i + borderWidth + squareSize / 2
: squareSize * i + offsetA; : squareSize * i + offsetA) + margin;
ctx.textAlign = hasBorder ? "center" : "left"; ctx.textAlign = hasBorder ? "center" : "left";
ctx.fillText(v, x, y); ctx.fillText(v, x, y);
@@ -65,7 +67,7 @@ const drawCoords = (
const x = hasBorder const x = hasBorder
? squareSize * i + borderWidth + squareSize / 2 ? squareSize * i + borderWidth + squareSize / 2
: squareSize * i + offsetA; : squareSize * i + offsetA;
const y = hasBorder ? size - borderWidth / 2 : size - offsetB; const y = (hasBorder ? size - borderWidth / 2 : size - offsetB) + margin;
ctx.textAlign = hasBorder ? "center" : "left"; ctx.textAlign = hasBorder ? "center" : "left";
ctx.fillText(v, x, y); ctx.fillText(v, x, y);

View File

@@ -0,0 +1,108 @@
import { Style } from "./../../types";
import drawText from "./drawText";
const MONTHS = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const drawExtraInfo = async (
ctx: CanvasRenderingContext2D,
width: number,
height: number,
scale: number,
margin: number,
style: Style,
data: { [key: string]: string | undefined },
flipped: boolean,
lastMove: boolean = true
) => {
ctx.fillStyle = style.coords.onBorder;
const fontSize = 20 * scale;
const offsetX = (margin - fontSize) / 2;
const offsetY = margin / 2;
if (data.White) {
const text =
data.White +
(data.WhiteElo && data.WhiteElo !== "?" ? ` (${data.WhiteElo})` : "");
drawText(
ctx,
text,
fontSize,
500,
offsetX,
(flipped ? offsetY : height - offsetY) * scale,
"left"
);
}
if (data.Black) {
const text =
data.Black +
(data.BlackElo && data.BlackElo !== "?" ? ` (${data.BlackElo})` : "");
drawText(
ctx,
text,
fontSize,
500,
offsetX,
(flipped ? height - offsetY : offsetY) * scale,
"left"
);
}
if (lastMove && data.Result) {
const [resultWhite, resultBlack] = data.Result.split("-");
const textWhite =
resultWhite === "0"
? "Lost: 0"
: resultWhite === "1"
? "Won: 1"
: "Draw: 1/2";
const textBlack =
resultBlack === "0"
? "Lost: 0"
: resultBlack === "1"
? "Won: 1"
: "Draw: 1/2";
drawText(
ctx,
textWhite,
fontSize,
500,
width - offsetX,
(flipped ? offsetY : height - offsetY) * scale,
"right"
);
drawText(
ctx,
textBlack,
fontSize,
500,
width - offsetX,
(flipped ? height - offsetY : offsetY) * scale,
"right"
);
}
};
export default drawExtraInfo;

View File

@@ -1,94 +0,0 @@
import { Style } from "./../../types";
import drawSquare from "../layers/drawSquare";
const MONTHS = [
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December",
];
const formatDate = (date: string) => {
const [y, m, d] = date.split(".").map(Number);
const month = Number.isNaN(m) ? null : MONTHS[m - 1];
const day = Number.isNaN(d) || month === null ? null : d;
const year = Number.isNaN(y) ? null : y;
return month && day && year
? `${month} ${day}, ${year}`
: month && year
? `${month} ${year}`
: year
? String(year)
: "";
};
const drawText = (
ctx: CanvasRenderingContext2D,
text: string,
fontSize: number,
fontWeight: number,
x: number,
y: number,
align: CanvasTextAlign
) => {
ctx.font = `${fontWeight} ${fontSize}px Ubuntu`;
ctx.textAlign = align;
ctx.textBaseline = "middle";
ctx.fillText(text, x, y);
};
const drawHeader = async (
ctx: CanvasRenderingContext2D,
size: number,
style: Style,
data: { [key: string]: string | undefined }
) => {
console.log(data);
const scale = size / 720;
ctx.clearRect(0, 0, size, size);
await drawSquare(ctx, size, 0, 0, style.border);
ctx.fillStyle = style.coords.onBorder;
if (data.White) {
drawText(ctx, data.White, 36 * scale, 700, size / 2, 200 * scale, "center");
}
drawText(ctx, "vs", 20 * scale, 500, size / 2, 260 * scale, "center");
if (data.Black) {
drawText(ctx, data.Black, 36 * scale, 700, size / 2, 320 * scale, "center");
}
if (data.Date) {
drawText(
ctx,
formatDate(data.Date),
20 * scale,
500,
size / 2,
500 * scale,
"center"
);
}
if (data.Event) {
drawText(ctx, data.Event, 24 * scale, 500, size / 2, 540 * scale, "center");
}
if (data.Site) {
drawText(ctx, data.Site, 20 * scale, 500, size / 2, 580 * scale, "center");
}
};
export default drawHeader;

View File

@@ -1,5 +1,6 @@
import { Style } from "./../../types"; import { Style } from "./../../types";
import drawSquare from "../layers/drawSquare"; import drawRectangle from "./drawRectangle";
import drawText from "./drawText";
const MONTHS = [ const MONTHS = [
"January", "January",
@@ -32,31 +33,18 @@ const formatDate = (date: string) => {
: ""; : "";
}; };
const drawText = (
ctx: CanvasRenderingContext2D,
text: string,
fontSize: number,
fontWeight: number,
x: number,
y: number,
align: CanvasTextAlign
) => {
ctx.font = `${fontWeight} ${fontSize}px Ubuntu`;
ctx.textAlign = align;
ctx.textBaseline = "middle";
ctx.fillText(text, x, y);
};
const drawHeader = async ( const drawHeader = async (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
size: number, size: number,
scale: number,
margin: number,
style: Style, style: Style,
data: { [key: string]: string | undefined }, data: { [key: string]: string | undefined },
flipped: boolean flipped: boolean
) => { ) => {
const scale = size / 720;
ctx.clearRect(0, 0, size, size); ctx.clearRect(0, 0, size, size);
await drawSquare(ctx, size, 0, 0, style.border); await drawRectangle(ctx, size, size + margin * 2, 0, 0, style.border);
// await drawRectangle()
ctx.fillStyle = style.coords.onBorder; ctx.fillStyle = style.coords.onBorder;
@@ -67,7 +55,7 @@ const drawHeader = async (
36 * scale, 36 * scale,
700, 700,
size / 2, size / 2,
(flipped ? 100 : size - 100) * scale, (flipped ? 100 : size - 100) * scale + margin,
"center" "center"
); );
} }
@@ -79,7 +67,7 @@ const drawHeader = async (
36 * scale, 36 * scale,
700, 700,
size / 2, size / 2,
(flipped ? size - 100 : 100) * scale, (flipped ? size - 100 : 100) * scale + margin,
"center" "center"
); );
} }
@@ -91,7 +79,7 @@ const drawHeader = async (
24 * scale, 24 * scale,
500, 500,
size / 2, size / 2,
(size / 2 - (data.Round ? 20 : 0)) * scale, (size / 2 - (data.Round ? 20 : 0)) * scale + margin,
"center" "center"
); );
} }
@@ -103,7 +91,7 @@ const drawHeader = async (
24 * scale, 24 * scale,
500, 500,
size / 2, size / 2,
(size / 2 + 20) * scale, (size / 2 + 20) * scale + margin,
"center" "center"
); );
} }
@@ -115,13 +103,21 @@ const drawHeader = async (
20 * scale, 20 * scale,
500, 500,
size / 2, size / 2,
450 * scale, 450 * scale + margin,
"center" "center"
); );
} }
if (data.Site) { if (data.Site) {
drawText(ctx, data.Site, 20 * scale, 500, size / 2, 480 * scale, "center"); drawText(
ctx,
data.Site,
20 * scale,
500,
size / 2,
480 * scale + margin,
"center"
);
} }
}; };

View File

@@ -1,6 +1,6 @@
import { Move } from "chess.js"; import { Move } from "chess.js";
import { Style, SquareStyle } from "../../types"; import { Style, SquareStyle } from "../../types";
import drawSquare from "./drawSquare"; import drawRectangle from "./drawRectangle";
const FILES = "abcdefghijklmnopqrstuwvxyz"; const FILES = "abcdefghijklmnopqrstuwvxyz";
@@ -18,15 +18,15 @@ const drawMoveIndicators = async (
{ dark, light, moveIndicator }: Style, { dark, light, moveIndicator }: Style,
borderWidth: number, borderWidth: number,
tiles: number, tiles: number,
flipped: boolean = false flipped: boolean,
margin: number
) => { ) => {
const [x0, y0] = notationToXY(move.from, flipped, tiles); const [x0, y0] = notationToXY(move.from, flipped, tiles);
const [x1, y1] = notationToXY(move.to, flipped, tiles); const [x1, y1] = notationToXY(move.to, flipped, tiles);
const [fromX, fromY, toX, toY] = [ const [fromX, fromY, toX, toY] = [x0, y0, x1, y1].map(
...notationToXY(move.from, flipped, tiles), (v) => v * squareSize + borderWidth
...notationToXY(move.to, flipped, tiles), );
].map((v) => v * squareSize + borderWidth);
let fromStyle; let fromStyle;
let toStyle; let toStyle;
@@ -43,8 +43,8 @@ const drawMoveIndicators = async (
toStyle = fromStyle; toStyle = fromStyle;
} }
drawSquare(ctx, squareSize, fromX, fromY, fromStyle); drawRectangle(ctx, squareSize, squareSize, fromX, fromY + margin, fromStyle);
drawSquare(ctx, squareSize, toX, toY, toStyle); drawRectangle(ctx, squareSize, squareSize, toX, toY + margin, toStyle);
}; };
export default drawMoveIndicators; export default drawMoveIndicators;

View File

@@ -8,10 +8,10 @@ const drawPieces = async (
borderWidth: number, borderWidth: number,
tiles: number, tiles: number,
flipped: boolean, flipped: boolean,
check?: "b" | "w", check: "b" | "w" | undefined,
mate?: "b" | "w", mate: "b" | "w" | undefined,
shadow: boolean = false, shadow: boolean,
blur: boolean = false margin: number
) => { ) => {
for (let y = 0; y < 8; y++) { for (let y = 0; y < 8; y++) {
for (let x = 0; x < 8; x++) { for (let x = 0; x < 8; x++) {
@@ -26,10 +26,6 @@ const drawPieces = async (
const filters = []; const filters = [];
if (blur) {
filters.push(`blur(5px)`);
}
if (shadow) { if (shadow) {
filters.push( filters.push(
`drop-shadow(${squareSize * 0.05}px ${squareSize * 0.05}px ${ `drop-shadow(${squareSize * 0.05}px ${squareSize * 0.05}px ${
@@ -51,7 +47,7 @@ const drawPieces = async (
ctx.drawImage( ctx.drawImage(
img, img,
borderWidth + file * squareSize, borderWidth + file * squareSize,
borderWidth + rank * squareSize, borderWidth + rank * squareSize + margin,
squareSize, squareSize,
squareSize squareSize
); );

View File

@@ -2,9 +2,10 @@ import { SquareStyle } from "../../types";
import createGradient from "../fill/createGradient"; import createGradient from "../fill/createGradient";
import createPattern from "../fill/createPattern"; import createPattern from "../fill/createPattern";
const drawSquare = async ( const drawRectangle = async (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
squareSize: number, width: number,
height: number,
x: number, x: number,
y: number, y: number,
squareStyle: SquareStyle squareStyle: SquareStyle
@@ -12,7 +13,7 @@ const drawSquare = async (
const fill = await (squareStyle.type === "solid" const fill = await (squareStyle.type === "solid"
? squareStyle.data.color ? squareStyle.data.color
: squareStyle.type === "gradient" : squareStyle.type === "gradient"
? createGradient(ctx, squareStyle.data, squareSize, x, y) ? createGradient(ctx, squareStyle.data, width, height, x, y)
: createPattern(ctx, squareStyle.data)); : createPattern(ctx, squareStyle.data));
if (fill === null) { if (fill === null) {
@@ -20,7 +21,7 @@ const drawSquare = async (
} }
ctx.fillStyle = fill; ctx.fillStyle = fill;
ctx.fillRect(x, y, squareSize, squareSize); ctx.fillRect(x, y, width, height);
}; };
export default drawSquare; export default drawRectangle;

View File

@@ -0,0 +1,16 @@
const drawText = (
ctx: CanvasRenderingContext2D,
text: string,
fontSize: number,
fontWeight: number,
x: number,
y: number,
align: CanvasTextAlign
) => {
ctx.font = `${fontWeight} ${fontSize}px Ubuntu`;
ctx.textAlign = align;
ctx.textBaseline = "middle";
ctx.fillText(text, x, y);
};
export default drawText;

View File

@@ -2,6 +2,12 @@ import { Style } from "../../types";
const style: Style = { const style: Style = {
name: "Calm", name: "Calm",
// background: {
// type: "solid",
// data: {
// color: "transparent",
// },
// },
background: { background: {
type: "gradient", type: "gradient",
data: { data: {

View File

@@ -9,6 +9,8 @@ const PGN_KEYS_TO_SHORT = {
Date: "D", Date: "D",
Result: "R", Result: "R",
FEN: "F", FEN: "F",
WhiteElo: "WE",
BlackElo: "BE",
}; };
const PGN_KEYS = Object.keys(PGN_KEYS_TO_SHORT); const PGN_KEYS = Object.keys(PGN_KEYS_TO_SHORT);

View File

@@ -3,12 +3,12 @@ import GIFLib from "gif.js";
class GIF { class GIF {
private gif: GIFLib; private gif: GIFLib;
constructor(size: number, loop: boolean) { constructor(width: number, height: number, loop: boolean) {
this.gif = new GIFLib({ this.gif = new GIFLib({
workers: 2, workers: 2,
quality: 10, quality: 10,
width: size, width,
height: size, height,
repeat: loop ? 0 : -1, repeat: loop ? 0 : -1,
}); });
} }
@@ -26,14 +26,14 @@ class GIF {
render(): Promise<File> { render(): Promise<File> {
return new Promise((resolve) => { return new Promise((resolve) => {
const timestamp = Date.now();
this.gif.on("finished", function (blob) { this.gif.on("finished", function (blob) {
const file = new File([blob], `board.gif`, { const file = new File([blob], `board_${timestamp}.gif`, {
type: "image/gif", type: "image/gif",
lastModified: Date.now(), lastModified: timestamp,
}); });
resolve(file); resolve(file);
// resolve(URL.createObjectURL(file));
}); });
this.gif.render(); this.gif.render();

View File

@@ -11,13 +11,16 @@ const createSimpleGIF = async (
size: number = 720 size: number = 720
) => { ) => {
const game = new Game().loadPGN(pgn); const game = new Game().loadPGN(pgn);
const board = new Board(8).setStyle(style).setSize(size).showBorder(); const board = new Board(8).setStyle(style).setSize(size).hideBorder();
const gif = new GIF(size, true); const gif = new GIF(board.width, board.height, true);
const header = game.getHeader();
await board.renderTitleScreen(game.getHeader()); await board.titleFrame(header);
board.render();
gif.add(board.toImgElement(), 5000); gif.add(board.toImgElement(), 5000);
await board.render(game.getBoardData()); await board.frame(game.getBoardData(), header);
board.render();
gif.add(board.toImgElement(), MOVE_TIME); gif.add(board.toImgElement(), MOVE_TIME);
while (true) { while (true) {
@@ -27,7 +30,8 @@ const createSimpleGIF = async (
break; break;
} }
await board.render(game.getBoardData(), move); await board.frame(game.getBoardData(), header, move);
board.render();
gif.add(board.toImgElement(), MOVE_TIME); gif.add(board.toImgElement(), MOVE_TIME);
} }

View File

@@ -19,9 +19,13 @@ const play = async (board: Board, pgn: string | null, interval: number) => {
game.loadPGN(pgn); game.loadPGN(pgn);
} }
await board.renderTitleScreen(game.getHeader()); const header = game.getHeader();
await delay(interval * 5);
await board.render(game.getBoardData()); await board.titleFrame(header);
board.render();
await board.frame(game.getBoardData(), header);
await delay(interval * 3);
board.render();
while (true) { while (true) {
const move = game.next(); const move = game.next();
@@ -30,8 +34,9 @@ const play = async (board: Board, pgn: string | null, interval: number) => {
break; break;
} }
await board.frame(game.getBoardData(), header, move);
await delay(interval); await delay(interval);
await board.render(game.getBoardData(), move); board.render();
} }
await delay(interval * 5); await delay(interval * 5);
@@ -50,25 +55,26 @@ const createDownloadLink = async (pgn: string, style: Style) => {
console.log(createDownloadLink.name); console.log(createDownloadLink.name);
const main = async () => { const main = async () => {
const style = styles.lila; const style = styles.calm;
// window.location.hash = // window.location.hash =
// "#QiBEdWtlIEthcmwgLyBDb3VudCBJc291YXJkCkQgMTg1OC4/Py4/PwpFIFBhcmlzClIgMS0wClMgUGFyaXMgRlJBClcgUGF1bCBNb3JwaHkKCmU0IGU1IE5mMyBkNiBkNCBCZzQgZHhlNSBCeGYzIFF4ZjMgZHhlNSBCYzQgTmY2IFFiMyBRZTcgTmMzIGM2IEJnNSBiNSBOeGI1IGN4YjUgQnhiNSsgTmJkNyBPLU8tTyBSZDggUnhkNyBSeGQ3IFJkMSBRZTYgQnhkNysgTnhkNyBRYjgrIE54YjggUmQ4Iw=="; // "#QiBEdWtlIEthcmwgLyBDb3VudCBJc291YXJkCkQgMTg1OC4/Py4/PwpFIFBhcmlzClIgMS0wClMgUGFyaXMgRlJBClcgUGF1bCBNb3JwaHkKCmU0IGU1IE5mMyBkNiBkNCBCZzQgZHhlNSBCeGYzIFF4ZjMgZHhlNSBCYzQgTmY2IFFiMyBRZTcgTmMzIGM2IEJnNSBiNSBOeGI1IGN4YjUgQnhiNSsgTmJkNyBPLU8tTyBSZDggUnhkNyBSeGQ3IFJkMSBRZTYgQnhkNysgTnhkNyBRYjgrIE54YjggUmQ4Iw==";
// const hash = window.location.hash; // const hash = window.location.hash;
// const pgn = hash === "" ? null : decompressPGN(hash.slice(1)); // const pgn = hash === "" ? null : decompressPGN(hash.slice(1));
const pgn = pgns[1]; const pgn = pgns[pgns.length - 1];
const board = new Board(8).setStyle(style).setSize(720).showBorder(); const board = new Board(8).setStyle(style).setSize(720).showBorder();
$app?.appendChild(board.canvas); $app?.appendChild(board.canvas);
console.log(pgn); console.log(pgn);
play(board, pgn, 1000); const interval = 1000;
play(board, pgn, interval);
// createDownloadLink(pgns[2], style).then((link) => { createDownloadLink(pgns[2], style).then((link) => {
// document.body.appendChild(link); document.body.appendChild(link);
// }); });
}; };
WebFont.load({ WebFont.load({

View File

@@ -3,6 +3,7 @@ body {
background-image: url(background.png); background-image: url(background.png);
background-attachment: fixed; background-attachment: fixed;
background-size: cover; background-size: cover;
background-position: center;
text-align: center; text-align: center;
padding-top: 50px; padding-top: 50px;
} }

View File

@@ -161,6 +161,25 @@ Rdc1 Bf6 28. Rc8+ 1-0`,
[Annotator "lichess.org"] [Annotator "lichess.org"]
1. b3 Nf6 { A01 Nimzo-Larsen Attack: Indian Variation } 2. Bb2 g6 3. Nc3 Bg7 4. d3 O-O 5. Qd2 d5 6. O-O-O e6 7. Nf3 Nbd7 8. e4 a5 9. exd5 Nxd5 10. Nxd5 exd5 11. Bxg7 Kxg7 12. g3 b5 13. Bg2 a4 14. b4 a3 15. Nd4 c6 16. Nb3 Nf6 17. Nc5 Nd7 18. Rhe1 Nxc5 19. d4 Na4 20. c3 Nb2 21. Kb1 Bf5+ 22. Ka1 Nxd1 23. Qxd1 Qf6 24. Qf3 Rae8 25. g4 Rxe1+ 26. Qd1 Rxd1# { Black wins by checkmate. } 0-1`, 1. b3 Nf6 { A01 Nimzo-Larsen Attack: Indian Variation } 2. Bb2 g6 3. Nc3 Bg7 4. d3 O-O 5. Qd2 d5 6. O-O-O e6 7. Nf3 Nbd7 8. e4 a5 9. exd5 Nxd5 10. Nxd5 exd5 11. Bxg7 Kxg7 12. g3 b5 13. Bg2 a4 14. b4 a3 15. Nd4 c6 16. Nb3 Nf6 17. Nc5 Nd7 18. Rhe1 Nxc5 19. d4 Na4 20. c3 Nb2 21. Kb1 Bf5+ 22. Ka1 Nxd1 23. Qxd1 Qf6 24. Qf3 Rae8 25. g4 Rxe1+ 26. Qd1 Rxd1# { Black wins by checkmate. } 0-1`,
`[Event "Casual Bullet game"]
[Site "https://lichess.org/kF9IVNaR"]
[Date "2022.01.20"]
[White "MG014"]
[Black "caderek"]
[Result "0-1"]
[UTCDate "2022.01.20"]
[UTCTime "05:03:34"]
[WhiteElo "1852"]
[BlackElo "1370"]
[Variant "Standard"]
[TimeControl "30+0"]
[ECO "A43"]
[Opening "Benoni Defense: Old Benoni"]
[Termination "Normal"]
[Annotator "lichess.org"]
1. d4 c5 { A43 Benoni Defense: Old Benoni } 2. Nf3 cxd4 3. Qxd4 Nc6 4. Qd1 g6 5. Nc3 Bg7 6. Bf4 e6 7. e3 Nge7 8. Bd3 O-O 9. Qd2 d5 10. O-O-O b6 11. e4 a5 12. exd5 Nxd5 13. Nxd5 exd5 14. Bb5 Bb7 15. Bxc6 Bxc6 16. a3 Qf6 17. Rhe1 Qxb2# { Black wins by checkmate. } 0-1`,
]; ];
export default pgns; export default pgns;