From 3e89d2998588f8e35c524e523ba2ee853f0f6475 Mon Sep 17 00:00:00 2001 From: Maze Winther Date: Mon, 20 Apr 2026 11:31:17 +0200 Subject: refactor: restructure files to their domains, new preview overlay system, and dep graph --- apps/web/src/graphics/definitions/star.ts | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 apps/web/src/graphics/definitions/star.ts (limited to 'apps/web/src/graphics/definitions/star.ts') diff --git a/apps/web/src/graphics/definitions/star.ts b/apps/web/src/graphics/definitions/star.ts new file mode 100644 index 00000000..3aa40fee --- /dev/null +++ b/apps/web/src/graphics/definitions/star.ts @@ -0,0 +1,109 @@ +import type { ParamDefinition } from "@/params"; +import { applyAlignedStroke } from "../stroke"; +import { STROKE_ALIGN_PARAM, type GraphicStrokeAlign } from "./shared"; +import type { GraphicDefinition } from "../types"; + +interface StarParams { + fill: string; + stroke: string; + strokeWidth: number; + strokeAlign: GraphicStrokeAlign; + points: number; + depth: number; +} + +const STAR_PARAMS: ParamDefinition[] = [ + { + key: "fill", + label: "Fill", + type: "color", + default: "#ffffff", + }, + { + key: "stroke", + label: "Color", + type: "color", + default: "#000000", + group: "stroke", + }, + { + key: "strokeWidth", + label: "Width", + type: "number", + default: 0, + min: 0, + max: 64, + step: 1, + shortLabel: "W", + group: "stroke", + }, + STROKE_ALIGN_PARAM, + { + key: "points", + label: "Points", + type: "number", + default: 5, + min: 3, + max: 12, + step: 1, + shortLabel: "P", + }, + { + key: "depth", + label: "Depth", + type: "number", + default: 45, + min: 1, + max: 99, + step: 1, + shortLabel: "D", + }, +]; + +export const starGraphicDefinition: GraphicDefinition = { + id: "star", + name: "Star", + keywords: ["star", "sparkle", "burst"], + params: STAR_PARAMS, + render({ ctx, params, width, height }) { + const fill = String(params.fill ?? "#ffffff"); + const stroke = String(params.stroke ?? "#000000"); + const strokeWidth = Math.max(0, Number(params.strokeWidth ?? 0)); + const strokeAlign = (params.strokeAlign ?? "center") as GraphicStrokeAlign; + const points = Math.max(3, Math.min(12, Math.round(Number(params.points ?? 5)))); + const depth = Math.max(1, Math.min(99, Number(params.depth ?? 45))) / 100; + const inset = strokeAlign === "center" ? strokeWidth / 2 : 0; + const outerRadius = Math.max(1, Math.min(width, height) / 2 - inset); + const innerRadius = outerRadius * depth; + const centerX = width / 2; + const centerY = height / 2; + + ctx.clearRect(0, 0, width, height); + const path = new Path2D(); + for (let index = 0; index < points * 2; index++) { + const radius = index % 2 === 0 ? outerRadius : innerRadius; + const angle = -Math.PI / 2 + (index * Math.PI) / points; + const x = centerX + Math.cos(angle) * radius; + const y = centerY + Math.sin(angle) * radius; + + if (index === 0) { + path.moveTo(x, y); + } else { + path.lineTo(x, y); + } + } + path.closePath(); + ctx.fillStyle = fill; + ctx.fill(path); + + if (strokeWidth > 0) { + applyAlignedStroke({ + ctx, + path, + strokeWidth, + strokeAlign, + strokeColor: stroke, + }); + } + }, +}; -- cgit v1.3.1