♻️ refacto: rename options

This commit is contained in:
platane
2022-04-12 21:35:04 +02:00
parent fb82d42d53
commit cce5c4514d
14 changed files with 116 additions and 74 deletions

View File

@@ -2,6 +2,10 @@
exports[`should parse /out.svg?{"color_snake":"yellow","color_dots":["#000","#111","#222","#333","#444"]} 1`] = ` exports[`should parse /out.svg?{"color_snake":"yellow","color_dots":["#000","#111","#222","#333","#444"]} 1`] = `
Object { Object {
"animationOptions": Object {
"frameDuration": 100,
"step": 1,
},
"drawOptions": Object { "drawOptions": Object {
"colorDotBorder": "#1b1f230a", "colorDotBorder": "#1b1f230a",
"colorDots": Array [ "colorDots": Array [
@@ -20,15 +24,15 @@ Object {
}, },
"filename": "/out.svg", "filename": "/out.svg",
"format": "svg", "format": "svg",
"gifOptions": Object {
"frameDuration": 100,
"step": 1,
},
} }
`; `;
exports[`should parse /out.svg?color_snake=orange&color_dots=#000,#111,#222,#333,#444 1`] = ` exports[`should parse /out.svg?color_snake=orange&color_dots=#000,#111,#222,#333,#444 1`] = `
Object { Object {
"animationOptions": Object {
"frameDuration": 100,
"step": 1,
},
"drawOptions": Object { "drawOptions": Object {
"colorDotBorder": "#1b1f230a", "colorDotBorder": "#1b1f230a",
"colorDots": Array [ "colorDots": Array [
@@ -47,15 +51,15 @@ Object {
}, },
"filename": "/out.svg", "filename": "/out.svg",
"format": "svg", "format": "svg",
"gifOptions": Object {
"frameDuration": 100,
"step": 1,
},
} }
`; `;
exports[`should parse /out.svg?color_snake=orange&color_dots=#000,#111,#222,#333,#444&dark_color_dots=#a00,#a11,#a22,#a33,#a44 1`] = ` exports[`should parse /out.svg?color_snake=orange&color_dots=#000,#111,#222,#333,#444&dark_color_dots=#a00,#a11,#a22,#a33,#a44 1`] = `
Object { Object {
"animationOptions": Object {
"frameDuration": 100,
"step": 1,
},
"drawOptions": Object { "drawOptions": Object {
"colorDotBorder": "#1b1f230a", "colorDotBorder": "#1b1f230a",
"colorDots": Array [ "colorDots": Array [
@@ -83,15 +87,15 @@ Object {
}, },
"filename": "/out.svg", "filename": "/out.svg",
"format": "svg", "format": "svg",
"gifOptions": Object {
"frameDuration": 100,
"step": 1,
},
} }
`; `;
exports[`should parse path/to/out.gif 1`] = ` exports[`should parse path/to/out.gif 1`] = `
Object { Object {
"animationOptions": Object {
"frameDuration": 100,
"step": 1,
},
"drawOptions": Object { "drawOptions": Object {
"colorDotBorder": "#1b1f230a", "colorDotBorder": "#1b1f230a",
"colorDots": Array [ "colorDots": Array [
@@ -121,9 +125,5 @@ Object {
}, },
"filename": "path/to/out.gif", "filename": "path/to/out.gif",
"format": "gif", "format": "gif",
"gifOptions": Object {
"frameDuration": 100,
"step": 1,
},
} }
`; `;

View File

@@ -3,17 +3,15 @@ import { userContributionToGrid } from "./userContributionToGrid";
import { getBestRoute } from "@snk/solver/getBestRoute"; import { getBestRoute } from "@snk/solver/getBestRoute";
import { snake4 } from "@snk/types/__fixtures__/snake"; import { snake4 } from "@snk/types/__fixtures__/snake";
import { getPathToPose } from "@snk/solver/getPathToPose"; import { getPathToPose } from "@snk/solver/getPathToPose";
import { Options as DrawOptions } from "@snk/svg-creator"; import type { DrawOptions as DrawOptions } from "@snk/svg-creator";
import type { AnimationOptions } from "@snk/gif-creator";
export const generateContributionSnake = async ( export const generateContributionSnake = async (
userName: string, userName: string,
outputs: ({ outputs: ({
format: "svg" | "gif"; format: "svg" | "gif";
drawOptions: DrawOptions; drawOptions: DrawOptions;
gifOptions: { animationOptions: AnimationOptions;
frameDuration: number;
step: number;
};
} | null)[] } | null)[]
) => { ) => {
console.log("🎣 fetching github user contribution"); console.log("🎣 fetching github user contribution");
@@ -29,17 +27,23 @@ export const generateContributionSnake = async (
return Promise.all( return Promise.all(
outputs.map(async (out, i) => { outputs.map(async (out, i) => {
if (!out) return; if (!out) return;
const { format, drawOptions, gifOptions } = out; const { format, drawOptions, animationOptions } = out;
switch (format) { switch (format) {
case "svg": { case "svg": {
console.log(`🖌 creating svg (outputs[${i}])`); console.log(`🖌 creating svg (outputs[${i}])`);
const { createSvg } = await import("@snk/svg-creator"); const { createSvg } = await import("@snk/svg-creator");
return createSvg(grid, chain, drawOptions, gifOptions); return createSvg(grid, cells, chain, drawOptions, animationOptions);
} }
case "gif": { case "gif": {
console.log(`📹 creating gif (outputs[${i}])`); console.log(`📹 creating gif (outputs[${i}])`);
const { createGif } = await import("@snk/gif-creator"); const { createGif } = await import("@snk/gif-creator");
return await createGif(grid, chain, drawOptions, gifOptions); return await createGif(
grid,
cells,
chain,
drawOptions,
animationOptions
);
} }
} }
}) })

View File

@@ -1,4 +1,5 @@
import { Options as DrawOptions } from "@snk/svg-creator"; import type { AnimationOptions } from "@snk/gif-creator";
import type { DrawOptions as DrawOptions } from "@snk/svg-creator";
import { palettes } from "./palettes"; import { palettes } from "./palettes";
export const parseOutputsOption = (lines: string[]) => lines.map(parseEntry); export const parseOutputsOption = (lines: string[]) => lines.map(parseEntry);
@@ -29,7 +30,7 @@ export const parseEntry = (entry: string) => {
sizeDot: 12, sizeDot: 12,
...palettes["default"], ...palettes["default"],
}; };
const gifOptions = { step: 1, frameDuration: 100 }; const animationOptions: AnimationOptions = { step: 1, frameDuration: 100 };
{ {
const palette = palettes[sp.get("palette")!]; const palette = palettes[sp.get("palette")!];
@@ -62,5 +63,10 @@ export const parseEntry = (entry: string) => {
if (sp.has("dark_color_snake") && drawOptions.dark) if (sp.has("dark_color_snake") && drawOptions.dark)
drawOptions.dark.colorSnake = sp.get("color_snake")!; drawOptions.dark.colorSnake = sp.get("color_snake")!;
return { filename, format: format as "svg" | "gif", drawOptions, gifOptions }; return {
filename,
format: format as "svg" | "gif",
drawOptions,
animationOptions,
};
}; };

View File

@@ -1,4 +1,4 @@
import { Options as DrawOptions } from "@snk/svg-creator"; import { DrawOptions as DrawOptions } from "@snk/svg-creator";
export const palettes: Record< export const palettes: Record<
string, string,

View File

@@ -1,7 +1,7 @@
import { Color, Grid } from "@snk/types/grid"; import { Color, Grid } from "@snk/types/grid";
import { drawLerpWorld, drawWorld } from "@snk/draw/drawWorld"; import { drawLerpWorld, drawWorld } from "@snk/draw/drawWorld";
import { Snake } from "@snk/types/snake"; import { Snake } from "@snk/types/snake";
import type { Options as DrawOptions } from "@snk/svg-creator"; import type { DrawOptions as DrawOptions } from "@snk/svg-creator";
export const drawOptions: DrawOptions = { export const drawOptions: DrawOptions = {
sizeDotBorderRadius: 2, sizeDotBorderRadius: 2,
@@ -68,7 +68,7 @@ export const createCanvas = ({
const draw = (grid: Grid, snake: Snake, stack: Color[]) => { const draw = (grid: Grid, snake: Snake, stack: Color[]) => {
ctx.clearRect(0, 0, 9999, 9999); ctx.clearRect(0, 0, 9999, 9999);
drawWorld(ctx, grid, snake, stack, drawOptions); drawWorld(ctx, grid, null, snake, stack, drawOptions);
}; };
const drawLerp = ( const drawLerp = (
@@ -79,7 +79,7 @@ export const createCanvas = ({
k: number k: number
) => { ) => {
ctx.clearRect(0, 0, 9999, 9999); ctx.clearRect(0, 0, 9999, 9999);
drawLerpWorld(ctx, grid, snake0, snake1, stack, k, drawOptions); drawLerpWorld(ctx, grid, null, snake0, snake1, stack, k, drawOptions);
}; };
const highlightCell = (x: number, y: number, color = "orange") => { const highlightCell = (x: number, y: number, color = "orange") => {

View File

@@ -3,6 +3,7 @@ import { step } from "@snk/solver/step";
import { isStableAndBound, stepSpring } from "./springUtils"; import { isStableAndBound, stepSpring } from "./springUtils";
import type { Res } from "@snk/github-user-contribution"; import type { Res } from "@snk/github-user-contribution";
import type { Snake } from "@snk/types/snake"; import type { Snake } from "@snk/types/snake";
import type { Point } from "@snk/types/point";
import { import {
drawLerpWorld, drawLerpWorld,
getCanvasWorldSize, getCanvasWorldSize,
@@ -12,6 +13,7 @@ import { userContributionToGrid } from "@snk/action/userContributionToGrid";
import { createSvg } from "@snk/svg-creator"; import { createSvg } from "@snk/svg-creator";
import { createRpcClient } from "./worker-utils"; import { createRpcClient } from "./worker-utils";
import type { API as WorkerAPI } from "./demo.interactive.worker"; import type { API as WorkerAPI } from "./demo.interactive.worker";
import { AnimationOptions } from "@snk/gif-creator";
const createForm = ({ const createForm = ({
onSubmit, onSubmit,
@@ -116,10 +118,12 @@ const createGithubProfile = () => {
const createViewer = ({ const createViewer = ({
grid0, grid0,
chain, chain,
cells,
drawOptions, drawOptions,
}: { }: {
grid0: Grid; grid0: Grid;
chain: Snake[]; chain: Snake[];
cells: Point[];
drawOptions: DrawOptions; drawOptions: DrawOptions;
}) => { }) => {
// //
@@ -159,7 +163,7 @@ const createViewer = ({
const k = spring.x % 1; const k = spring.x % 1;
ctx.clearRect(0, 0, 9999, 9999); ctx.clearRect(0, 0, 9999, 9999);
drawLerpWorld(ctx, grid, snake0, snake1, stack, k, drawOptions); drawLerpWorld(ctx, grid, null, snake0, snake1, stack, k, drawOptions);
if (!stable) animationFrame = requestAnimationFrame(loop); if (!stable) animationFrame = requestAnimationFrame(loop);
}; };
@@ -189,9 +193,9 @@ const createViewer = ({
// //
// svg // svg
const svgLink = document.createElement("a"); const svgLink = document.createElement("a");
const svgString = createSvg(grid0, chain, drawOptions, { const svgString = createSvg(grid0, cells, chain, drawOptions, {
frameDuration: 100, frameDuration: 100,
}); } as AnimationOptions);
const svgImageUri = `data:image/*;charset=utf-8;base64,${btoa(svgString)}`; const svgImageUri = `data:image/*;charset=utf-8;base64,${btoa(svgString)}`;
svgLink.href = svgImageUri; svgLink.href = svgImageUri;
svgLink.innerText = "github-user-contribution.svg"; svgLink.innerText = "github-user-contribution.svg";
@@ -237,7 +241,6 @@ const onSubmit = async (userName: string) => {
colorDots: colorScheme as any, colorDots: colorScheme as any,
colorEmpty: colorScheme[0], colorEmpty: colorScheme[0],
colorSnake: "purple", colorSnake: "purple",
cells,
}; };
const grid = userContributionToGrid(cells, colorScheme); const grid = userContributionToGrid(cells, colorScheme);
@@ -246,7 +249,7 @@ const onSubmit = async (userName: string) => {
dispose(); dispose();
createViewer({ grid0: grid, chain, drawOptions }); createViewer({ grid0: grid, chain, cells, drawOptions });
}; };
const worker = new Worker( const worker = new Worker(

View File

@@ -4,12 +4,15 @@ import { createSvg } from "@snk/svg-creator";
import { grid, snake } from "./sample"; import { grid, snake } from "./sample";
import { drawOptions } from "./canvas"; import { drawOptions } from "./canvas";
import { getPathToPose } from "@snk/solver/getPathToPose"; import { getPathToPose } from "@snk/solver/getPathToPose";
import type { AnimationOptions } from "@snk/gif-creator";
const chain = getBestRoute(grid, snake); const chain = getBestRoute(grid, snake);
chain.push(...getPathToPose(chain.slice(-1)[0], snake)!); chain.push(...getPathToPose(chain.slice(-1)[0], snake)!);
(async () => { (async () => {
const svg = await createSvg(grid, chain, drawOptions, { frameDuration: 200 }); const svg = await createSvg(grid, null, chain, drawOptions, {
frameDuration: 200,
} as AnimationOptions);
const container = document.createElement("div"); const container = document.createElement("div");
container.innerHTML = svg; container.innerHTML = svg;

View File

@@ -10,17 +10,17 @@ type Options = {
sizeCell: number; sizeCell: number;
sizeDot: number; sizeDot: number;
sizeDotBorderRadius: number; sizeDotBorderRadius: number;
cells?: Point[];
}; };
export const drawGrid = ( export const drawGrid = (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
grid: Grid, grid: Grid,
cells: Point[] | null,
o: Options o: Options
) => { ) => {
for (let x = grid.width; x--; ) for (let x = grid.width; x--; )
for (let y = grid.height; y--; ) { for (let y = grid.height; y--; ) {
if (!o.cells || o.cells.some((c) => c.x === x && c.y === y)) { if (!cells || cells.some((c) => c.x === x && c.y === y)) {
const c = getColor(grid, x, y); const c = getColor(grid, x, y);
// @ts-ignore // @ts-ignore
const color = !c ? o.colorEmpty : o.colorDots[c]; const color = !c ? o.colorEmpty : o.colorDots[c];

View File

@@ -1,8 +1,8 @@
import { drawGrid } from "./drawGrid"; import { drawGrid } from "./drawGrid";
import { drawSnake, drawSnakeLerp } from "./drawSnake"; import { drawSnake, drawSnakeLerp } from "./drawSnake";
import type { Grid, Color } from "@snk/types/grid"; import type { Grid, Color } from "@snk/types/grid";
import type { Point } from "@snk/types/point";
import type { Snake } from "@snk/types/snake"; import type { Snake } from "@snk/types/snake";
import type { Point } from "@snk/types/point";
export type Options = { export type Options = {
colorDots: Record<Color, string>; colorDots: Record<Color, string>;
@@ -12,7 +12,6 @@ export type Options = {
sizeCell: number; sizeCell: number;
sizeDot: number; sizeDot: number;
sizeDotBorderRadius: number; sizeDotBorderRadius: number;
cells?: Point[];
}; };
export const drawStack = ( export const drawStack = (
@@ -37,6 +36,7 @@ export const drawStack = (
export const drawWorld = ( export const drawWorld = (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
grid: Grid, grid: Grid,
cells: Point[] | null,
snake: Snake, snake: Snake,
stack: Color[], stack: Color[],
o: Options o: Options
@@ -44,7 +44,7 @@ export const drawWorld = (
ctx.save(); ctx.save();
ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); ctx.translate(1 * o.sizeCell, 2 * o.sizeCell);
drawGrid(ctx, grid, o); drawGrid(ctx, grid, cells, o);
drawSnake(ctx, snake, o); drawSnake(ctx, snake, o);
ctx.restore(); ctx.restore();
@@ -68,6 +68,7 @@ export const drawWorld = (
export const drawLerpWorld = ( export const drawLerpWorld = (
ctx: CanvasRenderingContext2D, ctx: CanvasRenderingContext2D,
grid: Grid, grid: Grid,
cells: Point[] | null,
snake0: Snake, snake0: Snake,
snake1: Snake, snake1: Snake,
stack: Color[], stack: Color[],
@@ -77,7 +78,7 @@ export const drawLerpWorld = (
ctx.save(); ctx.save();
ctx.translate(1 * o.sizeCell, 2 * o.sizeCell); ctx.translate(1 * o.sizeCell, 2 * o.sizeCell);
drawGrid(ctx, grid, o); drawGrid(ctx, grid, cells, o);
drawSnakeLerp(ctx, snake0, snake1, k, o); drawSnakeLerp(ctx, snake0, snake1, k, o);
ctx.translate(0, (grid.height + 2) * o.sizeCell); ctx.translate(0, (grid.height + 2) * o.sizeCell);

View File

@@ -2,7 +2,7 @@ import * as fs from "fs";
import { performance } from "perf_hooks"; import { performance } from "perf_hooks";
import { createSnakeFromCells } from "@snk/types/snake"; import { createSnakeFromCells } from "@snk/types/snake";
import { realistic as grid } from "@snk/types/__fixtures__/grid"; import { realistic as grid } from "@snk/types/__fixtures__/grid";
import { createGif } from ".."; import { AnimationOptions, createGif } from "..";
import { getBestRoute } from "@snk/solver/getBestRoute"; import { getBestRoute } from "@snk/solver/getBestRoute";
import { getPathToPose } from "@snk/solver/getPathToPose"; import { getPathToPose } from "@snk/solver/getPathToPose";
import type { Options as DrawOptions } from "@snk/draw/drawWorld"; import type { Options as DrawOptions } from "@snk/draw/drawWorld";
@@ -35,7 +35,7 @@ const drawOptions: DrawOptions = {
colorSnake: "purple", colorSnake: "purple",
}; };
const gifOptions = { frameDuration: 100, step: 1 }; const animationOptions: AnimationOptions = { frameDuration: 100, step: 1 };
(async () => { (async () => {
for ( for (
@@ -50,7 +50,13 @@ const gifOptions = { frameDuration: 100, step: 1 };
const chainL = chain.slice(0, length); const chainL = chain.slice(0, length);
for (let k = 0; k < 10 && (Date.now() - start < 10 * 1000 || k < 2); k++) { for (let k = 0; k < 10 && (Date.now() - start < 10 * 1000 || k < 2); k++) {
const s = performance.now(); const s = performance.now();
buffer = await createGif(grid, chainL, drawOptions, gifOptions); buffer = await createGif(
grid,
null,
chainL,
drawOptions,
animationOptions
);
stats.push(performance.now() - s); stats.push(performance.now() - s);
} }

View File

@@ -1,6 +1,6 @@
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import { createGif } from ".."; import { AnimationOptions, createGif } from "..";
import * as grids from "@snk/types/__fixtures__/grid"; import * as grids from "@snk/types/__fixtures__/grid";
import { snake3 as snake } from "@snk/types/__fixtures__/snake"; import { snake3 as snake } from "@snk/types/__fixtures__/snake";
import { createSnakeFromCells, nextSnake } from "@snk/types/snake"; import { createSnakeFromCells, nextSnake } from "@snk/types/snake";
@@ -20,7 +20,7 @@ const drawOptions: DrawOptions = {
colorSnake: "purple", colorSnake: "purple",
}; };
const gifOptions = { frameDuration: 200, step: 1 }; const animationOptions: AnimationOptions = { frameDuration: 200, step: 1 };
const dir = path.resolve(__dirname, "__snapshots__"); const dir = path.resolve(__dirname, "__snapshots__");
@@ -40,7 +40,13 @@ for (const key of [
const chain = [snake, ...getBestRoute(grid, snake)!]; const chain = [snake, ...getBestRoute(grid, snake)!];
const gif = await createGif(grid, chain, drawOptions, gifOptions); const gif = await createGif(
grid,
null,
chain,
drawOptions,
animationOptions
);
expect(gif).toBeDefined(); expect(gif).toBeDefined();
@@ -64,7 +70,7 @@ it(`should generate swipper`, async () => {
} }
} }
const gif = await createGif(grid, chain, drawOptions, gifOptions); const gif = await createGif(grid, null, chain, drawOptions, animationOptions);
expect(gif).toBeDefined(); expect(gif).toBeDefined();

View File

@@ -5,10 +5,11 @@ import { createCanvas } from "canvas";
import { Grid, copyGrid, Color } from "@snk/types/grid"; import { Grid, copyGrid, Color } from "@snk/types/grid";
import { Snake } from "@snk/types/snake"; import { Snake } from "@snk/types/snake";
import { import {
Options, Options as DrawOptions,
drawLerpWorld, drawLerpWorld,
getCanvasWorldSize, getCanvasWorldSize,
} from "@snk/draw/drawWorld"; } from "@snk/draw/drawWorld";
import type { Point } from "@snk/types/point";
import { step } from "@snk/solver/step"; import { step } from "@snk/solver/step";
import tmp from "tmp"; import tmp from "tmp";
import gifsicle from "gifsicle"; import gifsicle from "gifsicle";
@@ -29,11 +30,14 @@ const withTmpDir = async <T>(
} }
}; };
export type AnimationOptions = { frameDuration: number; step: number };
export const createGif = async ( export const createGif = async (
grid0: Grid, grid0: Grid,
cells: Point[] | null,
chain: Snake[], chain: Snake[],
drawOptions: Options, drawOptions: DrawOptions,
gifOptions: { frameDuration: number; step: number } animationOptions: AnimationOptions
) => ) =>
withTmpDir(async (dir) => { withTmpDir(async (dir) => {
const { width, height } = getCanvasWorldSize(grid0, drawOptions); const { width, height } = getCanvasWorldSize(grid0, drawOptions);
@@ -46,7 +50,7 @@ export const createGif = async (
const encoder = new GIFEncoder(width, height, "neuquant", true); const encoder = new GIFEncoder(width, height, "neuquant", true);
encoder.setRepeat(0); encoder.setRepeat(0);
encoder.setDelay(gifOptions.frameDuration); encoder.setDelay(animationOptions.frameDuration);
encoder.start(); encoder.start();
for (let i = 0; i < chain.length; i += 1) { for (let i = 0; i < chain.length; i += 1) {
@@ -54,17 +58,18 @@ export const createGif = async (
const snake1 = chain[Math.min(chain.length - 1, i + 1)]; const snake1 = chain[Math.min(chain.length - 1, i + 1)];
step(grid, stack, snake0); step(grid, stack, snake0);
for (let k = 0; k < gifOptions.step; k++) { for (let k = 0; k < animationOptions.step; k++) {
ctx.clearRect(0, 0, width, height); ctx.clearRect(0, 0, width, height);
ctx.fillStyle = "#fff"; ctx.fillStyle = "#fff";
ctx.fillRect(0, 0, width, height); ctx.fillRect(0, 0, width, height);
drawLerpWorld( drawLerpWorld(
ctx, ctx,
grid, grid,
cells,
snake0, snake0,
snake1, snake1,
stack, stack,
k / gifOptions.step, k / animationOptions.step,
drawOptions drawOptions
); );

View File

@@ -1,11 +1,12 @@
import * as fs from "fs"; import * as fs from "fs";
import * as path from "path"; import * as path from "path";
import { createSvg, Options } from ".."; import { createSvg, DrawOptions as DrawOptions } from "..";
import * as grids from "@snk/types/__fixtures__/grid"; import * as grids from "@snk/types/__fixtures__/grid";
import { snake3 as snake } from "@snk/types/__fixtures__/snake"; import { snake3 as snake } from "@snk/types/__fixtures__/snake";
import { getBestRoute } from "@snk/solver/getBestRoute"; import { getBestRoute } from "@snk/solver/getBestRoute";
import { AnimationOptions } from "@snk/gif-creator";
const drawOptions: Options = { const drawOptions: DrawOptions = {
sizeDotBorderRadius: 2, sizeDotBorderRadius: 2,
sizeCell: 16, sizeCell: 16,
sizeDot: 12, sizeDot: 12,
@@ -19,7 +20,7 @@ const drawOptions: Options = {
}, },
}; };
const gifOptions = { frameDuration: 100, step: 1 }; const animationOptions: AnimationOptions = { frameDuration: 100, step: 1 };
const dir = path.resolve(__dirname, "__snapshots__"); const dir = path.resolve(__dirname, "__snapshots__");
@@ -31,7 +32,13 @@ for (const [key, grid] of Object.entries(grids))
it(`should generate ${key} svg`, async () => { it(`should generate ${key} svg`, async () => {
const chain = [snake, ...getBestRoute(grid, snake)!]; const chain = [snake, ...getBestRoute(grid, snake)!];
const svg = await createSvg(grid, chain, drawOptions, gifOptions); const svg = await createSvg(
grid,
null,
chain,
drawOptions,
animationOptions
);
expect(svg).toBeDefined(); expect(svg).toBeDefined();

View File

@@ -14,8 +14,9 @@ import { createGrid } from "./grid";
import { createStack } from "./stack"; import { createStack } from "./stack";
import { h } from "./utils"; import { h } from "./utils";
import * as csso from "csso"; import * as csso from "csso";
import { AnimationOptions } from "@snk/gif-creator";
export type Options = { export type DrawOptions = {
colorDots: Record<Color, string>; colorDots: Record<Color, string>;
colorEmpty: string; colorEmpty: string;
colorDotBorder: string; colorDotBorder: string;
@@ -23,7 +24,6 @@ export type Options = {
sizeCell: number; sizeCell: number;
sizeDot: number; sizeDot: number;
sizeDotBorderRadius: number; sizeDotBorderRadius: number;
cells?: Point[];
dark?: { dark?: {
colorDots: Record<Color, string>; colorDots: Record<Color, string>;
colorEmpty: string; colorEmpty: string;
@@ -40,12 +40,12 @@ const getCellsFromGrid = ({ width, height }: Grid) =>
const createLivingCells = ( const createLivingCells = (
grid0: Grid, grid0: Grid,
chain: Snake[], chain: Snake[],
drawOptions: Options cells: Point[] | null
) => { ) => {
const cells: (Point & { const livingCells: (Point & {
t: number | null; t: number | null;
color: Color | Empty; color: Color | Empty;
})[] = (drawOptions.cells ?? getCellsFromGrid(grid0)).map(({ x, y }) => ({ })[] = (cells ?? getCellsFromGrid(grid0)).map(({ x, y }) => ({
x, x,
y, y,
t: null, t: null,
@@ -60,31 +60,32 @@ const createLivingCells = (
if (isInside(grid, x, y) && !isEmpty(getColor(grid, x, y))) { if (isInside(grid, x, y) && !isEmpty(getColor(grid, x, y))) {
setColorEmpty(grid, x, y); setColorEmpty(grid, x, y);
const cell = cells.find((c) => c.x === x && c.y === y)!; const cell = livingCells.find((c) => c.x === x && c.y === y)!;
cell.t = i / chain.length; cell.t = i / chain.length;
} }
} }
return cells; return livingCells;
}; };
export const createSvg = ( export const createSvg = (
grid: Grid, grid: Grid,
cells: Point[] | null,
chain: Snake[], chain: Snake[],
drawOptions: Options, drawOptions: DrawOptions,
gifOptions: { frameDuration: number } animationOptions: Pick<AnimationOptions, "frameDuration">
) => { ) => {
const width = (grid.width + 2) * drawOptions.sizeCell; const width = (grid.width + 2) * drawOptions.sizeCell;
const height = (grid.height + 5) * drawOptions.sizeCell; const height = (grid.height + 5) * drawOptions.sizeCell;
const duration = gifOptions.frameDuration * chain.length; const duration = animationOptions.frameDuration * chain.length;
const cells = createLivingCells(grid, chain, drawOptions); const livingCells = createLivingCells(grid, chain, cells);
const elements = [ const elements = [
createGrid(cells, drawOptions, duration), createGrid(livingCells, drawOptions, duration),
createStack( createStack(
cells, livingCells,
drawOptions, drawOptions,
grid.width * drawOptions.sizeCell, grid.width * drawOptions.sizeCell,
(grid.height + 2) * drawOptions.sizeCell, (grid.height + 2) * drawOptions.sizeCell,
@@ -134,7 +135,7 @@ export const createSvg = (
const optimizeCss = (css: string) => csso.minify(css).css; const optimizeCss = (css: string) => csso.minify(css).css;
const optimizeSvg = (svg: string) => svg; const optimizeSvg = (svg: string) => svg;
const generateColorVar = (drawOptions: Options) => const generateColorVar = (drawOptions: DrawOptions) =>
` `
:root { :root {
--cb: ${drawOptions.colorDotBorder}; --cb: ${drawOptions.colorDotBorder};