diff --git a/frontend/src/adapters/gateways/EChartsOptionBuilder/wordcloudOptionBuilder.ts b/frontend/src/adapters/gateways/EChartsOptionBuilder/wordcloudOptionBuilder.ts index 62eb2a0..b1e252d 100644 --- a/frontend/src/adapters/gateways/EChartsOptionBuilder/wordcloudOptionBuilder.ts +++ b/frontend/src/adapters/gateways/EChartsOptionBuilder/wordcloudOptionBuilder.ts @@ -53,24 +53,24 @@ function gradientColor(ratio: number, colors: string[]): string { * Create a canvas maskImage for the given shape. * 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; const canvas = document.createElement('canvas'); - canvas.width = size; - canvas.height = size; + canvas.width = w; + canvas.height = h; const ctx = canvas.getContext('2d'); if (!ctx) return null; // Fill white (excluded area) 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'; - const cx = size / 2; - const cy = size / 2; - const r = size * 0.45; + const cx = w / 2; + const cy = h / 2; + const r = Math.min(w, h) * 0.48; switch (shape) { case 'circle': @@ -145,22 +145,23 @@ function createShapeMask(shape: string, size: number): HTMLCanvasElement | null default: // Fallback: fill entire canvas (rectangle) - ctx.fillRect(0, 0, size, size); + ctx.fillRect(0, 0, w, h); break; } return canvas; } -// Cache mask images to avoid re-creating on every render +// Cache mask images keyed by "shape-WxH" const maskCache = new Map(); -function getMask(shape: string): HTMLCanvasElement | null { +function getMask(shape: string, w = 1024, h = 700): HTMLCanvasElement | 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; - const mask = createShapeMask(shape, 512); - if (mask) maskCache.set(shape, mask); + const mask = createShapeMask(shape, w, h); + if (mask) maskCache.set(key, mask); return mask; }