import type { AppState } from "../types"; import type { StaticCanvasRenderConfig } from "../scene/types"; import { THEME, THEME_FILTER } from "../constants"; export const fillCircle = ( context: CanvasRenderingContext2D, cx: number, cy: number, radius: number, stroke = true, ) => { context.beginPath(); context.arc(cx, cy, radius, 0, Math.PI * 2); context.fill(); if (stroke) { context.stroke(); } }; export const getNormalizedCanvasDimensions = ( canvas: HTMLCanvasElement, scale: number, ): [number, number] => { // When doing calculations based on canvas width we should used normalized one return [canvas.width / scale, canvas.height / scale]; }; export const bootstrapCanvas = ({ canvas, scale, normalizedWidth, normalizedHeight, theme, isExporting, canvasBackgroundColor, }: { canvas: HTMLCanvasElement; scale: number; normalizedWidth: number; normalizedHeight: number; theme?: AppState["theme"]; // static canvas only isExporting?: StaticCanvasRenderConfig["isExporting"]; canvasBackgroundColor?: string | null; }): CanvasRenderingContext2D => { const context = canvas.getContext("2d")!; context.setTransform(1, 0, 0, 1, 0, 0); context.scale(scale, scale); if (isExporting && theme === THEME.DARK) { context.filter = THEME_FILTER; } // Paint background if (typeof canvasBackgroundColor === "string") { const hasTransparence = canvasBackgroundColor === "transparent" || canvasBackgroundColor.length === 5 || // #RGBA canvasBackgroundColor.length === 9 || // #RRGGBBA /(hsla|rgba)\(/.test(canvasBackgroundColor); if (hasTransparence) { context.clearRect(0, 0, normalizedWidth, normalizedHeight); } context.save(); context.fillStyle = canvasBackgroundColor; context.fillRect(0, 0, normalizedWidth, normalizedHeight); context.restore(); } else { context.clearRect(0, 0, normalizedWidth, normalizedHeight); } return context; };