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.
* 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<string, HTMLCanvasElement>();
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;
}