54 lines
1.4 KiB
TypeScript
54 lines
1.4 KiB
TypeScript
import { createCanvas, loadImage } from "canvas";
|
|
import QRCode from "qrcode";
|
|
|
|
const CANVAS_SIZE = 1000;
|
|
const LOGO_PADDING = 1;
|
|
|
|
export const renderQRCodeToCanvas = async (
|
|
content: string,
|
|
logoUrl: string | undefined,
|
|
) => {
|
|
const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);
|
|
const errorCorrectionLevel: QRCode.QRCodeErrorCorrectionLevel = logoUrl
|
|
? "H"
|
|
: "M";
|
|
|
|
await QRCode.toCanvas(canvas, content, {
|
|
errorCorrectionLevel,
|
|
width: CANVAS_SIZE,
|
|
margin: 1,
|
|
});
|
|
|
|
if (!logoUrl) return canvas;
|
|
|
|
const qrCode = QRCode.create(content, { errorCorrectionLevel });
|
|
const moduleCount = qrCode.modules.size + 2;
|
|
|
|
const logoImage = await loadImage(logoUrl);
|
|
|
|
const moduleSize = CANVAS_SIZE / moduleCount;
|
|
|
|
let logoModules = Math.floor(moduleCount * 0.3);
|
|
if (logoModules % 2 !== moduleCount % 2) {
|
|
logoModules += 1;
|
|
}
|
|
|
|
const backgroundSize = logoModules * moduleSize + 1;
|
|
const backgroundPosition = (moduleSize * (moduleCount - logoModules)) / 2;
|
|
|
|
const logoSize = backgroundSize - LOGO_PADDING * 2;
|
|
const logoPosition = backgroundPosition + LOGO_PADDING;
|
|
|
|
const ctx = canvas.getContext("2d");
|
|
ctx.fillStyle = "white";
|
|
ctx.fillRect(
|
|
backgroundPosition,
|
|
backgroundPosition,
|
|
backgroundSize,
|
|
backgroundSize,
|
|
);
|
|
ctx.drawImage(logoImage, logoPosition, logoPosition, logoSize, logoSize);
|
|
|
|
return canvas;
|
|
};
|