diff --git a/apps/web/src/api.ts b/apps/web/src/api.ts index 51e65e3..8fe2944 100644 --- a/apps/web/src/api.ts +++ b/apps/web/src/api.ts @@ -20,13 +20,17 @@ export function searchWorkshop(q: string, page = 1): Promise { /** * Trace an image into a vector shape, BSON-deserializing the proxy response. - * `mode` controls how the region is derived (`alpha`, `bw`, `color`). + * `mode` controls how the region is derived (`alpha`, `bw`, `color`); a + * non-zero `offset` insets (negative) or outsets (positive) the shape in + * pixels. */ export async function traceImage( url: string, mode: 'alpha' | 'bw' | 'color' = 'alpha', + offset?: number, ): Promise { const params = new URLSearchParams({ url, mode }); + if (offset !== undefined) params.set('offset', String(offset)); const res = await fetch(`${BASE}/trace?${params.toString()}`); if (!res.ok) { const body = (await res.json().catch(() => null)) as { error?: string } | null; diff --git a/apps/web/src/components/viewers/TokenViewer.tsx b/apps/web/src/components/viewers/TokenViewer.tsx index d2b046b..4eea612 100644 --- a/apps/web/src/components/viewers/TokenViewer.tsx +++ b/apps/web/src/components/viewers/TokenViewer.tsx @@ -14,6 +14,9 @@ import { assetUrl } from './assetUrl'; const TOKEN_SIZE = 1.8; +/** How far (in trace pixels) the token silhouette is inset from the artwork. */ +const TRACE_INSET = 2; + /** * A token: a short extruded shape with the texture on its top face. Uses * `CustomImage.ImageURL` (falling back to `ImageSecondaryURL`), with a neutral @@ -46,7 +49,7 @@ function TokenMesh({ url, thickness }: { url?: string; thickness: number }) { let cancelled = false; setTrace(null); if (!url) return; - traceImage(url, 'alpha') + traceImage(url, 'alpha', -TRACE_INSET) .then((result) => { if (!cancelled && result.shape) { setTrace({