Files
pihkaal-me/app/utils/canvas.ts

101 lines
2.4 KiB
TypeScript

export const fillTextCentered = (
ctx: CanvasRenderingContext2D,
text: string,
x: number,
y: number,
width: number,
): number => {
const measure = ctx.measureText(text);
const textX = Math.floor(x + width / 2 - measure.actualBoundingBoxRight / 2);
const textY =
measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent;
ctx.fillText(text, textX, y + textY);
return measure.actualBoundingBoxAscent + measure.actualBoundingBoxDescent + 1;
};
export const fillImageTextHCentered = (
ctx: CanvasRenderingContext2D,
image: AtlasImage,
text: string,
x: number,
y: number,
width: number,
gap: number,
) => {
const { actualBoundingBoxRight: textWidth } = ctx.measureText(text);
const totalWidth = textWidth + gap + image.rect.width;
const groupX = Math.floor(x + width / 2 - totalWidth / 2);
image.draw(ctx, groupX, y);
ctx.fillText(text, groupX + gap + image.rect.width, y);
};
export const fillTextHCentered = (
ctx: CanvasRenderingContext2D,
text: string,
x: number,
y: number,
width: number,
) => {
const measure = ctx.measureText(text);
const textX = Math.floor(x + width / 2 - measure.actualBoundingBoxRight / 2);
ctx.fillText(text, textX, y);
};
export const fillTextHCenteredMultiline = (
ctx: CanvasRenderingContext2D,
text: string,
x: number,
y: number,
width: number,
lineHeight: number,
) => {
const lines = text.split("\n");
for (let i = 0, y = 20; i < lines.length; i += 1, y += lineHeight) {
fillTextHCentered(ctx, lines[i]!, 0, y, width);
}
};
export const fillTextWordWrapped = (
ctx: CanvasRenderingContext2D,
text: string,
x: number,
y: number,
width: number,
lineHeight?: number,
): number => {
const words = text.split(" ");
let line = "";
let currentY = y;
let lineCount = 0;
const height =
lineHeight ||
ctx.measureText("M").actualBoundingBoxAscent +
ctx.measureText("M").actualBoundingBoxDescent;
currentY += height;
for (let i = 0; i < words.length; i++) {
const testLine = line + (line ? " " : "") + words[i];
const metrics = ctx.measureText(testLine);
const testWidth = metrics.width;
if (testWidth > width && line) {
ctx.fillText(line, x, currentY);
line = words[i]!;
currentY += height;
lineCount++;
} else {
line = testLine;
}
}
if (line) {
ctx.fillText(line, x, currentY);
lineCount++;
}
return lineCount * height;
};