refactor(renderer): create canvas in renderer
This commit is contained in:
6
app.vue
6
app.vue
@@ -2,7 +2,6 @@
|
|||||||
import { renderQRCodeToCanvas } from "@/utils/renderer";
|
import { renderQRCodeToCanvas } from "@/utils/renderer";
|
||||||
import { IMAGE_FORMATS, LOGOS } from "@/utils/settings";
|
import { IMAGE_FORMATS, LOGOS } from "@/utils/settings";
|
||||||
|
|
||||||
const canvas = ref(null);
|
|
||||||
const form = ref(null);
|
const form = ref(null);
|
||||||
const qrCode = ref(undefined);
|
const qrCode = ref(undefined);
|
||||||
|
|
||||||
@@ -49,9 +48,9 @@ const updateQRCode = async () => {
|
|||||||
if (!isValidState.value) return;
|
if (!isValidState.value) return;
|
||||||
|
|
||||||
const logoUrl = state.hasLogo ? `/logos/${state.logo}.png` : undefined;
|
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 () => {
|
const copyUrl = async () => {
|
||||||
@@ -106,7 +105,6 @@ const arrayToUnion = (array: string[]) =>
|
|||||||
<template>
|
<template>
|
||||||
<div role="main" class="flex h-[100vh] items-center justify-center">
|
<div role="main" class="flex h-[100vh] items-center justify-center">
|
||||||
<NuxtRouteAnnouncer />
|
<NuxtRouteAnnouncer />
|
||||||
<canvas ref="canvas" class="hidden" />
|
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="p-5 w-full max-w-[850px] flex flex-col justify-center space-y-4"
|
class="p-5 w-full max-w-[850px] flex flex-col justify-center space-y-4"
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
import { createCanvas } from "canvas";
|
|
||||||
import { resolve } from "path";
|
import { resolve } from "path";
|
||||||
import sharp from "sharp";
|
import sharp from "sharp";
|
||||||
import { CANVAS_SIZE, renderQRCodeToCanvas } from "~/utils/renderer";
|
import { renderQRCodeToCanvas } from "~/utils/renderer";
|
||||||
import { settingsSchema } from "~/utils/settings";
|
import { settingsSchema } from "~/utils/settings";
|
||||||
|
|
||||||
export default defineEventHandler(async (event) => {
|
export default defineEventHandler(async (event) => {
|
||||||
@@ -21,9 +20,8 @@ export default defineEventHandler(async (event) => {
|
|||||||
|
|
||||||
const { format, logo, content } = parsed.data;
|
const { format, logo, content } = parsed.data;
|
||||||
|
|
||||||
const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);
|
|
||||||
const logoUrl = logo ? resolve("public", `logos/${logo}.png`) : undefined;
|
const logoUrl = logo ? resolve("public", `logos/${logo}.png`) : undefined;
|
||||||
await renderQRCodeToCanvas(canvas, content, logoUrl);
|
const canvas = await renderQRCodeToCanvas(content, logoUrl);
|
||||||
|
|
||||||
let image = canvas.toBuffer();
|
let image = canvas.toBuffer();
|
||||||
if (format !== "png") {
|
if (format !== "png") {
|
||||||
|
|||||||
@@ -1,47 +1,50 @@
|
|||||||
import { loadImage, type Canvas, type CanvasRenderingContext2D } from "canvas";
|
import { createCanvas, loadImage } from "canvas";
|
||||||
import QRCode from "qrcode";
|
import QRCode from "qrcode";
|
||||||
|
|
||||||
export const CANVAS_SIZE = 1000;
|
const CANVAS_SIZE = 1000;
|
||||||
export const LOGO_PADDING = 1;
|
const LOGO_PADDING = 1;
|
||||||
|
|
||||||
export const renderQRCodeToCanvas = async (
|
export const renderQRCodeToCanvas = async (
|
||||||
canvas: HTMLCanvasElement | Canvas,
|
|
||||||
content: string,
|
content: string,
|
||||||
logoUrl: string | undefined,
|
logoUrl: string | undefined,
|
||||||
) => {
|
) => {
|
||||||
|
const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE);
|
||||||
|
|
||||||
await QRCode.toCanvas(canvas, content, {
|
await QRCode.toCanvas(canvas, content, {
|
||||||
errorCorrectionLevel: "H",
|
errorCorrectionLevel: "H",
|
||||||
width: CANVAS_SIZE,
|
width: CANVAS_SIZE,
|
||||||
margin: 1,
|
margin: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (logoUrl) {
|
if (!logoUrl) return canvas;
|
||||||
const qrCode = QRCode.create(content, { errorCorrectionLevel: "H" });
|
|
||||||
const moduleCount = qrCode.modules.size + 2;
|
|
||||||
|
|
||||||
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);
|
const moduleSize = CANVAS_SIZE / moduleCount;
|
||||||
if (logoModules % 2 !== moduleCount % 2) {
|
|
||||||
logoModules += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
const backgroundSize = logoModules * moduleSize + 1;
|
let logoModules = Math.floor(moduleCount * 0.3);
|
||||||
const backgroundPosition = (moduleSize * (moduleCount - logoModules)) / 2;
|
if (logoModules % 2 !== moduleCount % 2) {
|
||||||
|
logoModules += 1;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user