fix: use 1024x700 mask canvas for better shape coverage

Previous 512x512 square mask was too small, causing most words to
be excluded. Now uses 1024x700 (16:11 ratio) to match typical chart
containers, with r=48% fill for maximum word area.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hailin 2026-04-05 21:28:10 -07:00
parent 8fb5caef07
commit e7d7745f74
1 changed files with 15 additions and 14 deletions

View File

@ -53,24 +53,24 @@ function gradientColor(ratio: number, colors: string[]): string {
* Create a canvas maskImage for the given shape. * Create a canvas maskImage for the given shape.
* White = excluded, Black = where words can be placed. * White = excluded, Black = where words can be placed.
*/ */
function createShapeMask(shape: string, size: number): HTMLCanvasElement | null { function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement | null {
if (typeof document === 'undefined') return null; if (typeof document === 'undefined') return null;
const canvas = document.createElement('canvas'); const canvas = document.createElement('canvas');
canvas.width = size; canvas.width = w;
canvas.height = size; canvas.height = h;
const ctx = canvas.getContext('2d'); const ctx = canvas.getContext('2d');
if (!ctx) return null; if (!ctx) return null;
// Fill white (excluded area) // Fill white (excluded area)
ctx.fillStyle = '#fff'; ctx.fillStyle = '#fff';
ctx.fillRect(0, 0, size, size); ctx.fillRect(0, 0, w, h);
// Draw black shape (word area) // Draw black shape (word area) — fill as much as possible
ctx.fillStyle = '#000'; ctx.fillStyle = '#000';
const cx = size / 2; const cx = w / 2;
const cy = size / 2; const cy = h / 2;
const r = size * 0.45; const r = Math.min(w, h) * 0.48;
switch (shape) { switch (shape) {
case 'circle': case 'circle':
@ -145,22 +145,23 @@ function createShapeMask(shape: string, size: number): HTMLCanvasElement | null
default: default:
// Fallback: fill entire canvas (rectangle) // Fallback: fill entire canvas (rectangle)
ctx.fillRect(0, 0, size, size); ctx.fillRect(0, 0, w, h);
break; break;
} }
return canvas; return canvas;
} }
// Cache mask images to avoid re-creating on every render // Cache mask images keyed by "shape-WxH"
const maskCache = new Map<string, HTMLCanvasElement>(); const maskCache = new Map<string, HTMLCanvasElement>();
function getMask(shape: string): HTMLCanvasElement | null { function getMask(shape: string, w = 1024, h = 700): HTMLCanvasElement | null {
if (shape === 'rectangle') return null; if (shape === 'rectangle') return null;
const cached = maskCache.get(shape); const key = `${shape}-${w}x${h}`;
const cached = maskCache.get(key);
if (cached) return cached; if (cached) return cached;
const mask = createShapeMask(shape, 512); const mask = createShapeMask(shape, w, h);
if (mask) maskCache.set(shape, mask); if (mask) maskCache.set(key, mask);
return mask; return mask;
} }