icy3dw/src/client/object/canvas-utils.ts

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 };
}
}