From 9b8b7f5e19502bfd1d61e13cab94fa1e40226a65 Mon Sep 17 00:00:00 2001 From: Severin Ibarluzea Date: Fri, 27 Jun 2025 11:26:16 -0700 Subject: [PATCH 1/3] feat: scale text size and improve bounds --- lib/constants.ts | 2 ++ lib/drawGraphicsToCanvas.ts | 13 +++++++++++-- lib/getSvgFromGraphicsObject.ts | 13 +++++++++++-- lib/index.ts | 1 + tests/SVGRenderer.test.tsx | 2 +- tests/__snapshots__/texts.snap.svg | 8 ++++---- tests/getBounds.test.ts | 17 +++++++++++++++++ tests/getSvgFromGraphicsObject.test.ts | 4 +++- 8 files changed, 50 insertions(+), 10 deletions(-) create mode 100644 lib/constants.ts create mode 100644 tests/getBounds.test.ts diff --git a/lib/constants.ts b/lib/constants.ts new file mode 100644 index 0000000..1a001d0 --- /dev/null +++ b/lib/constants.ts @@ -0,0 +1,2 @@ +export const FONT_SIZE_WIDTH_RATIO = 0.6 +export const FONT_SIZE_HEIGHT_RATIO = 1 diff --git a/lib/drawGraphicsToCanvas.ts b/lib/drawGraphicsToCanvas.ts index 628837b..381810a 100644 --- a/lib/drawGraphicsToCanvas.ts +++ b/lib/drawGraphicsToCanvas.ts @@ -12,6 +12,7 @@ import type { TransformOptions, } from "./types" import { defaultColors } from "site/components/InteractiveGraphics/defaultColors" +import { FONT_SIZE_WIDTH_RATIO, FONT_SIZE_HEIGHT_RATIO } from "./constants" /** * Computes a transformation matrix based on a provided viewbox @@ -79,7 +80,15 @@ export function getBounds(graphics: GraphicsObject): Viewbox { { x: circle.center.x, y: circle.center.y - circle.radius }, // top { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom ]), - ...(graphics.texts || []).map((text) => ({ x: text.x, y: text.y })), + ...(graphics.texts || []).flatMap((text) => { + const fontSize = text.fontSize ?? 12 + const width = text.text.length * fontSize * FONT_SIZE_WIDTH_RATIO + const height = fontSize * FONT_SIZE_HEIGHT_RATIO + return [ + { x: text.x, y: text.y }, + { x: text.x + width, y: text.y + height }, + ] + }), ] if (points.length === 0) { @@ -296,7 +305,7 @@ export function drawGraphicsToCanvas( graphics.texts.forEach((text) => { const projected = applyToPoint(matrix, { x: text.x, y: text.y }) ctx.fillStyle = text.color || "black" - ctx.font = `${text.fontSize ?? 12}px sans-serif` + ctx.font = `${(text.fontSize ?? 12) * Math.abs(matrix.a)}px sans-serif` const anchor = text.anchorSide ?? "center" const alignMap: Record = { diff --git a/lib/getSvgFromGraphicsObject.ts b/lib/getSvgFromGraphicsObject.ts index d0b94eb..6575e77 100644 --- a/lib/getSvgFromGraphicsObject.ts +++ b/lib/getSvgFromGraphicsObject.ts @@ -10,6 +10,7 @@ import { import type { GraphicsObject, Point } from "./types" import { stringify } from "svgson" import pretty from "pretty" +import { FONT_SIZE_WIDTH_RATIO, FONT_SIZE_HEIGHT_RATIO } from "./constants" const DEFAULT_SVG_SIZE = 640 const PADDING = 40 @@ -41,7 +42,15 @@ function getBounds(graphics: GraphicsObject): Bounds { { x: circle.center.x, y: circle.center.y - circle.radius }, // top { x: circle.center.x, y: circle.center.y + circle.radius }, // bottom ]), - ...(graphics.texts || []).map((t) => ({ x: t.x, y: t.y })), + ...(graphics.texts || []).flatMap((t) => { + const fontSize = t.fontSize ?? 12 + const width = t.text.length * fontSize * FONT_SIZE_WIDTH_RATIO + const height = fontSize * FONT_SIZE_HEIGHT_RATIO + return [ + { x: t.x, y: t.y }, + { x: t.x + width, y: t.y + height }, + ] + }), ] if (points.length === 0) { @@ -337,7 +346,7 @@ export function getSvgFromGraphicsObject( x: projected.x.toString(), y: projected.y.toString(), fill: txt.color || "black", - "font-size": (txt.fontSize ?? 12).toString(), + "font-size": ((txt.fontSize ?? 12) * Math.abs(matrix.a)).toString(), "font-family": "sans-serif", "text-anchor": alignMap[anchor], "dominant-baseline": baselineMap[anchor], diff --git a/lib/index.ts b/lib/index.ts index 28925df..c5613b3 100644 --- a/lib/index.ts +++ b/lib/index.ts @@ -29,6 +29,7 @@ export { } from "./drawGraphicsToCanvas" export { translateGraphics } from "./translateGraphics" export { mergeGraphics } from "./mergeGraphics" +export { FONT_SIZE_WIDTH_RATIO, FONT_SIZE_HEIGHT_RATIO } from "./constants" export function getSvgFromLogString(logString: string): string { const objects = getGraphicsObjectsFromLogString(logString) diff --git a/tests/SVGRenderer.test.tsx b/tests/SVGRenderer.test.tsx index f9536a2..5216b15 100644 --- a/tests/SVGRenderer.test.tsx +++ b/tests/SVGRenderer.test.tsx @@ -56,7 +56,7 @@ describe("SVGRenderer", () => { document.body.removeChild(container) throw error } - }, 0) + }, 50) }) }) }) diff --git a/tests/__snapshots__/texts.snap.svg b/tests/__snapshots__/texts.snap.svg index dc58b2b..cdce728 100644 --- a/tests/__snapshots__/texts.snap.svg +++ b/tests/__snapshots__/texts.snap.svg @@ -1,4 +1,4 @@ -Hello +Hello