feat: init
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
import Canvas, { registerFont} from "canvas";
|
||||
|
||||
|
||||
const wrapText = (ctx, text, maxWidth) => {
|
||||
registerFont(`./assets/fonts/Impact.ttf`, {
|
||||
family: "Impact",
|
||||
});
|
||||
if(ctx.measureText(text).width < maxWidth) return [text];
|
||||
if(ctx.measureText("W").width > maxWidth) return null;
|
||||
const words = text.split(" ");
|
||||
const lines = [];
|
||||
let line = "";
|
||||
while(words.length > 0) {
|
||||
let split = false;
|
||||
while(ctx.measureText(words[0]).width >= maxWidth){
|
||||
const tmp = words[0];
|
||||
words[0] = tmp.slice(0, -1);
|
||||
if(split){
|
||||
words[1] = `${tmp.slice(-1)}${words[1]}`
|
||||
}else{
|
||||
split = true;
|
||||
words.splice(1, 0, tmp.slice(-1));
|
||||
}
|
||||
}
|
||||
if (ctx.measureText(`${line}${words[0]}`).width < maxWidth) {
|
||||
line += `${words.shift()} `;
|
||||
} else {
|
||||
lines.push(line.trim());
|
||||
line = "";
|
||||
}
|
||||
if (words.length === 0) lines.push(line.trim());
|
||||
}
|
||||
return lines;
|
||||
}
|
||||
|
||||
|
||||
const generateMeme = async (imageSrc, topText, bottomText) => {
|
||||
const base = await Canvas.loadImage(imageSrc);
|
||||
const canvas = Canvas.createCanvas(base.width, base.height);
|
||||
const ctx = canvas.getContext("2d");
|
||||
|
||||
ctx.drawImage(base, 0, 0);
|
||||
const fontSize = Math.round(base.height / 10);
|
||||
ctx.font = `bold ${fontSize}px Impact`;
|
||||
ctx.fillStyle = "white";
|
||||
ctx.textAlign = "center";
|
||||
ctx.textBaseline = "top";
|
||||
|
||||
const topLines = await wrapText(ctx, topText, base.width - 10)
|
||||
if (topLines) {
|
||||
for (let i = 0; i < topLines.length; i++) {
|
||||
const textHeight = i * fontSize + i * 10;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.lineWidth = 5;
|
||||
ctx.strokeText(topLines[i], base.width / 2, textHeight);
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillText(topLines[i], base.width / 2, textHeight);
|
||||
}
|
||||
}
|
||||
const bottomLines = await wrapText(ctx, bottomText, base.width - 10);
|
||||
if (bottomLines) {
|
||||
ctx.textBaseline = "bottom";
|
||||
const initial =
|
||||
base.height -
|
||||
(bottomLines.length - 1) * fontSize -
|
||||
(bottomLines.length - 1) * 10;
|
||||
for (let i = 0; i < bottomLines.length; i++) {
|
||||
const textHeight = initial + i * fontSize + i * 10;
|
||||
ctx.strokeStyle = "black";
|
||||
ctx.lineWidth = 5;
|
||||
ctx.strokeText(bottomLines[i], base.width / 2, textHeight);
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillText(bottomLines[i], base.width / 2, textHeight);
|
||||
}
|
||||
}
|
||||
|
||||
return canvas.toBuffer();
|
||||
}
|
||||
|
||||
export default generateMeme;
|
||||
Reference in New Issue
Block a user