Integrate worker to offload main thread from heavy tasks
This commit is contained in:
108
wwwroot/core/namecards/nameCardCreator.js
Normal file
108
wwwroot/core/namecards/nameCardCreator.js
Normal file
@@ -0,0 +1,108 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import { createCanvas, loadImage, registerFont } from "canvas";
|
||||
|
||||
export class NameCardCreator {
|
||||
constructor(templatePath) {
|
||||
this.templatePath = templatePath;
|
||||
this.loadFont("./wwwroot/assets/fonts/Fredoka/static/Fredoka-Bold.ttf")
|
||||
}
|
||||
|
||||
loadFont(fontPath) {
|
||||
const fullPath = path.resolve(fontPath);
|
||||
if (!fs.existsSync(fullPath)) {
|
||||
throw new Error(`Font file not found at ${fullPath}`);
|
||||
}
|
||||
registerFont(fullPath, {family: "Fredoka Bold"});
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée la carte de bienvenue entièrement via Canvas
|
||||
*/
|
||||
async getWelcomeCard(avatarPath, name) {
|
||||
try {
|
||||
const canvasWidth = 3000;
|
||||
const canvasHeight = 1000;
|
||||
const canvas = createCanvas(canvasWidth, canvasHeight);
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
const template = await loadImage(this.templatePath);
|
||||
ctx.drawImage(template, 0, 0, canvasWidth, canvasHeight);
|
||||
|
||||
const avatarSize = 675;
|
||||
const avatar = await loadImage(avatarPath);
|
||||
|
||||
const avatarX = 225;
|
||||
const avatarY = (canvasHeight - avatarSize) / 2;
|
||||
ctx.save();
|
||||
ctx.beginPath();
|
||||
ctx.arc(
|
||||
avatarX + avatarSize / 2,
|
||||
avatarY + avatarSize / 2,
|
||||
avatarSize / 2,
|
||||
0,
|
||||
Math.PI * 2,
|
||||
true
|
||||
);
|
||||
ctx.closePath();
|
||||
ctx.clip();
|
||||
ctx.drawImage(avatar, avatarX, avatarY, avatarSize, avatarSize);
|
||||
ctx.restore();
|
||||
|
||||
ctx.lineWidth = 8;
|
||||
ctx.strokeStyle = "#ffffff";
|
||||
ctx.beginPath();
|
||||
ctx.arc(
|
||||
avatarX + avatarSize / 2,
|
||||
avatarY + avatarSize / 2,
|
||||
avatarSize / 2,
|
||||
0,
|
||||
Math.PI * 2,
|
||||
true
|
||||
);
|
||||
ctx.stroke();
|
||||
|
||||
const messageX = avatarX + 1525;
|
||||
const messageY = (canvasHeight / 2)+75;
|
||||
ctx.fillStyle = "#ede6e6";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "middle";
|
||||
|
||||
ctx.font = '115px "Fredoka Bold"';
|
||||
|
||||
const lines = [`Welcome ${name}, to the`, "Spicy Jail ~"];
|
||||
const lineHeight = 130;
|
||||
const startY = messageY - ((lines.length - 1) / 2) * lineHeight;
|
||||
|
||||
lines.forEach((line, i) => {
|
||||
ctx.fillText(line, messageX, startY + i * lineHeight);
|
||||
});
|
||||
|
||||
const result = this.scallDown(canvas, 1500, 500)
|
||||
|
||||
fs.writeFileSync("./tests/result/namecard.png", result);
|
||||
console.log("✅ Name card created: namecard.png");
|
||||
return result;
|
||||
} catch (err) {
|
||||
console.error("Error creating name card:", err);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @param target
|
||||
* @param width
|
||||
* @param height
|
||||
* @returns {Buffer}
|
||||
*/
|
||||
scallDown(target, width, height) {
|
||||
const smallCanvas = createCanvas(width, height);
|
||||
const smallCtx = smallCanvas.getContext('2d');
|
||||
|
||||
smallCtx.drawImage(target, 0, 0, width, height);
|
||||
return smallCanvas.toBuffer();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user