refactor(renderer): create canvas in renderer

This commit is contained in:
Pihkaal
2024-10-12 18:44:12 +02:00
parent d0855dde8c
commit 43ecff853e
3 changed files with 35 additions and 36 deletions

View File

@@ -2,7 +2,6 @@
import { renderQRCodeToCanvas } from "@/utils/renderer";
import { IMAGE_FORMATS, LOGOS } from "@/utils/settings";
const canvas = ref(null);
const form = ref(null);
const qrCode = ref(undefined);
@@ -49,9 +48,9 @@ const updateQRCode = async () => {
if (!isValidState.value) return;
const logoUrl = state.hasLogo ? `/logos/${state.logo}.png` : undefined;
await renderQRCodeToCanvas(canvas.value, state.content, logoUrl);
const canvas = await renderQRCodeToCanvas(state.content, logoUrl);
qrCode.value = canvas.value.toDataURL(`image/${state.format}`);
qrCode.value = canvas.toDataURL(`image/${state.format}`);
};
const copyUrl = async () => {
@@ -106,7 +105,6 @@ const arrayToUnion = (array: string[]) =>
<template>
<div role="main" class="flex h-[100vh] items-center justify-center">
<NuxtRouteAnnouncer />
<canvas ref="canvas" class="hidden" />
<div
class="p-5 w-full max-w-[850px] flex flex-col justify-center space-y-4"

View File

@@ -1,7 +1,6 @@
import { createCanvas } from "canvas";
import { resolve } from "path";
import sharp from "sharp";
import { CANVAS_SIZE, renderQRCodeToCanvas } from "~/utils/renderer";
import { renderQRCodeToCanvas } from "~/utils/renderer";
import { settingsSchema } from "~/utils/settings";
export default defineEventHandler(async (event) => {
@@ -21,9 +20,8 @@ export default defineEventHandler(async (event) => {
const { format, logo, content } = parsed.data;
const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);
const logoUrl = logo ? resolve("public", `logos/${logo}.png`) : undefined;
await renderQRCodeToCanvas(canvas, content, logoUrl);
const canvas = await renderQRCodeToCanvas(content, logoUrl);
let image = canvas.toBuffer();
if (format !== "png") {

View File

@@ -1,47 +1,50 @@
import { loadImage, type Canvas, type CanvasRenderingContext2D } from "canvas";
import { createCanvas, loadImage } from "canvas";
import QRCode from "qrcode";
export const CANVAS_SIZE = 1000;
export const LOGO_PADDING = 1;
const CANVAS_SIZE = 1000;
const LOGO_PADDING = 1;
export const renderQRCodeToCanvas = async (
canvas: HTMLCanvasElement | Canvas,
content: string,
logoUrl: string | undefined,
) => {
const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);
await QRCode.toCanvas(canvas, content, {
errorCorrectionLevel: "H",
width: CANVAS_SIZE,
margin: 1,
});
if (logoUrl) {
const qrCode = QRCode.create(content, { errorCorrectionLevel: "H" });
const moduleCount = qrCode.modules.size + 2;
if (!logoUrl) return canvas;
const logoImage = await loadImage(logoUrl);
const qrCode = QRCode.create(content, { errorCorrectionLevel: "H" });
const moduleCount = qrCode.modules.size + 2;
const moduleSize = CANVAS_SIZE / moduleCount;
const logoImage = await loadImage(logoUrl);
let logoModules = Math.floor(moduleCount * 0.3);
if (logoModules % 2 !== moduleCount % 2) {
logoModules += 1;
}
const moduleSize = CANVAS_SIZE / moduleCount;
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") as CanvasRenderingContext2D;
ctx.fillStyle = "white";
ctx.fillRect(
backgroundPosition,
backgroundPosition,
backgroundSize,
backgroundSize,
);
ctx.drawImage(logoImage, logoPosition, logoPosition, logoSize, logoSize);
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;
};