fix: stretch wordcloud shapes to fill container using ellipse radii
Changed from square min(w,h) radius to separate rx/ry that use the full width and height of the container. Shapes now fill the entire chart area instead of being constrained to a small square. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
e7d7745f74
commit
f8ef83506a
|
|
@ -66,25 +66,27 @@ function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement
|
|||
ctx.fillStyle = '#fff';
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
|
||||
// Draw black shape (word area) — fill as much as possible
|
||||
// Draw black shape (word area) — stretch to fill container
|
||||
ctx.fillStyle = '#000';
|
||||
const cx = w / 2;
|
||||
const cy = h / 2;
|
||||
const r = Math.min(w, h) * 0.48;
|
||||
const rx = w * 0.48; // horizontal radius
|
||||
const ry = h * 0.48; // vertical radius
|
||||
|
||||
switch (shape) {
|
||||
case 'circle':
|
||||
case 'circle': {
|
||||
ctx.beginPath();
|
||||
ctx.arc(cx, cy, r, 0, Math.PI * 2);
|
||||
ctx.ellipse(cx, cy, rx, ry, 0, 0, Math.PI * 2);
|
||||
ctx.fill();
|
||||
break;
|
||||
}
|
||||
|
||||
case 'cardioid': {
|
||||
ctx.beginPath();
|
||||
for (let angle = 0; angle < Math.PI * 2; angle += 0.01) {
|
||||
const rr = r * 0.85 * (1 - Math.sin(angle));
|
||||
const x = cx + rr * Math.cos(angle);
|
||||
const y = cy - rr * Math.sin(angle) + r * 0.3;
|
||||
const scale = 0.85 * (1 - Math.sin(angle));
|
||||
const x = cx + rx * scale * Math.cos(angle);
|
||||
const y = cy - ry * scale * Math.sin(angle) + ry * 0.3;
|
||||
if (angle === 0) ctx.moveTo(x, y);
|
||||
else ctx.lineTo(x, y);
|
||||
}
|
||||
|
|
@ -95,10 +97,10 @@ function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement
|
|||
|
||||
case 'diamond': {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(cx, cy - r);
|
||||
ctx.lineTo(cx + r, cy);
|
||||
ctx.lineTo(cx, cy + r);
|
||||
ctx.lineTo(cx - r, cy);
|
||||
ctx.moveTo(cx, cy - ry);
|
||||
ctx.lineTo(cx + rx, cy);
|
||||
ctx.lineTo(cx, cy + ry);
|
||||
ctx.lineTo(cx - rx, cy);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
break;
|
||||
|
|
@ -106,9 +108,9 @@ function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement
|
|||
|
||||
case 'triangle': {
|
||||
ctx.beginPath();
|
||||
ctx.moveTo(cx, cy - r);
|
||||
ctx.lineTo(cx + r * 0.87, cy + r * 0.5);
|
||||
ctx.lineTo(cx - r * 0.87, cy + r * 0.5);
|
||||
ctx.moveTo(cx, cy - ry);
|
||||
ctx.lineTo(cx + rx, cy + ry);
|
||||
ctx.lineTo(cx - rx, cy + ry);
|
||||
ctx.closePath();
|
||||
ctx.fill();
|
||||
break;
|
||||
|
|
@ -118,9 +120,10 @@ function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement
|
|||
ctx.beginPath();
|
||||
for (let i = 0; i < 10; i++) {
|
||||
const angle = (Math.PI / 2) + (i * Math.PI / 5);
|
||||
const rr = i % 2 === 0 ? r : r * 0.4;
|
||||
const x = cx + rr * Math.cos(angle);
|
||||
const y = cy - rr * Math.sin(angle);
|
||||
const outerX = i % 2 === 0 ? rx : rx * 0.4;
|
||||
const outerY = i % 2 === 0 ? ry : ry * 0.4;
|
||||
const x = cx + outerX * Math.cos(angle);
|
||||
const y = cy - outerY * Math.sin(angle);
|
||||
if (i === 0) ctx.moveTo(x, y);
|
||||
else ctx.lineTo(x, y);
|
||||
}
|
||||
|
|
@ -133,8 +136,8 @@ function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement
|
|||
ctx.beginPath();
|
||||
for (let i = 0; i < 5; i++) {
|
||||
const angle = (Math.PI / 2) + (i * 2 * Math.PI / 5);
|
||||
const x = cx + r * Math.cos(angle);
|
||||
const y = cy - r * Math.sin(angle);
|
||||
const x = cx + rx * Math.cos(angle);
|
||||
const y = cy - ry * Math.sin(angle);
|
||||
if (i === 0) ctx.moveTo(x, y);
|
||||
else ctx.lineTo(x, y);
|
||||
}
|
||||
|
|
@ -144,7 +147,6 @@ function createShapeMask(shape: string, w: number, h: number): HTMLCanvasElement
|
|||
}
|
||||
|
||||
default:
|
||||
// Fallback: fill entire canvas (rectangle)
|
||||
ctx.fillRect(0, 0, w, h);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue