61 lines
1.7 KiB
TypeScript
61 lines
1.7 KiB
TypeScript
import { CanvasTexture, LinearFilter, ClampToEdgeWrapping } from 'three';
|
|
|
|
export class CanvasUtils {
|
|
public createTextCanvas(
|
|
text: string | string[],
|
|
bold = true,
|
|
fontSize = 16,
|
|
padding = 4,
|
|
): { texture: CanvasTexture; width: number; height: number } {
|
|
const ctx = document.createElement('canvas').getContext('2d');
|
|
const font = `${fontSize}px${bold ? ' bold' : ''} sans`;
|
|
|
|
const lines = Array.isArray(text) ? text : [text];
|
|
const lineWidths = [];
|
|
let longestLine = 0;
|
|
|
|
// Measure the text bounds
|
|
ctx.font = font;
|
|
lines.forEach((line) => {
|
|
const lineWidth = ctx.measureText(line).width;
|
|
if (longestLine < lineWidth) {
|
|
longestLine = lineWidth;
|
|
}
|
|
lineWidths.push(lineWidth);
|
|
});
|
|
|
|
const width = longestLine + padding * 2;
|
|
const textHeight = fontSize * lines.length;
|
|
const height = textHeight + padding * 2;
|
|
|
|
// Resize canvas
|
|
ctx.canvas.width = width;
|
|
ctx.canvas.height = height;
|
|
|
|
// Set text parameters
|
|
ctx.font = font;
|
|
ctx.textAlign = 'center';
|
|
|
|
// Draw background
|
|
ctx.fillStyle = '#fff';
|
|
ctx.fillRect(0, 0, width, height);
|
|
|
|
// Scale the text to fit within the canvas
|
|
const scaleFactor = Math.min(1, width / longestLine);
|
|
ctx.translate(width / 2 - padding, padding + fontSize / 2);
|
|
ctx.scale(scaleFactor, 1);
|
|
ctx.fillStyle = '#000';
|
|
lines.forEach((line, i) => {
|
|
ctx.fillText(line, padding, i * fontSize + padding);
|
|
});
|
|
|
|
// Create texture with appropriate flags
|
|
const texture = new CanvasTexture(ctx.canvas);
|
|
texture.minFilter = LinearFilter;
|
|
texture.wrapS = ClampToEdgeWrapping;
|
|
texture.wrapT = ClampToEdgeWrapping;
|
|
|
|
return { texture, width, height };
|
|
}
|
|
}
|