diff --git a/app.vue b/app.vue index 703cb0a..744edf9 100644 --- a/app.vue +++ b/app.vue @@ -23,7 +23,10 @@ const state = reactive({ }); const isValidState = computed( - () => state.content && state.logo && state.format, + () => + state.content && + ((state.hasLogo && state.logo) || !state.hasLogo) && + state.format, ); const BASE_API_URL = "http://localhost:3000/api"; @@ -32,7 +35,7 @@ const apiUrl = computed(() => { if (!isValidState.value) return ""; const params = new URLSearchParams({ - logo: state.logo, + ...(state.hasLogo && { logo: state.logo }), format: state.format, content: state.content, }); @@ -45,7 +48,7 @@ const updateQRCode = async () => { if (!isValidState.value) return; - const logoUrl = `/logos/${state.logo}.png`; + const logoUrl = state.hasLogo ? `/logos/${state.logo}.png` : undefined; await renderQRCodeToCanvas(canvas.value, state.content, logoUrl); qrCode.value = canvas.value.toDataURL(`image/${state.format}`); @@ -134,6 +137,7 @@ const arrayToUnion = (array: string[]) => v-model="state.hasLogo" class="mb-1.5" label="Logo" + @change="updateQRCode" /> diff --git a/server/api/index.ts b/server/api/index.ts index 5ffc50a..14f0079 100644 --- a/server/api/index.ts +++ b/server/api/index.ts @@ -22,7 +22,7 @@ export default defineEventHandler(async (event) => { const { format, logo, content } = parsed.data; const canvas = createCanvas(CANVAS_SIZE, CANVAS_SIZE); - const logoUrl = resolve("public", `logos/${logo}.png`); + const logoUrl = logo ? resolve("public", `logos/${logo}.png`) : undefined; await renderQRCodeToCanvas(canvas, content, logoUrl); let image = canvas.toBuffer(); diff --git a/utils/renderer.ts b/utils/renderer.ts index 2e99170..0d2ef4b 100644 --- a/utils/renderer.ts +++ b/utils/renderer.ts @@ -7,7 +7,7 @@ export const LOGO_PADDING = 1; export const renderQRCodeToCanvas = async ( canvas: HTMLCanvasElement | Canvas, content: string, - logoUrl: string, + logoUrl: string | undefined, ) => { await QRCode.toCanvas(canvas, content, { errorCorrectionLevel: "H", @@ -15,31 +15,33 @@ export const renderQRCodeToCanvas = async ( margin: 1, }); - const qrCode = QRCode.create(content, { errorCorrectionLevel: "H" }); - const moduleCount = qrCode.modules.size + 2; + if (logoUrl) { + const qrCode = QRCode.create(content, { errorCorrectionLevel: "H" }); + const moduleCount = qrCode.modules.size + 2; - const logoImage = await loadImage(logoUrl); + const logoImage = await loadImage(logoUrl); - const moduleSize = CANVAS_SIZE / moduleCount; + const moduleSize = CANVAS_SIZE / moduleCount; - let logoModules = Math.floor(moduleCount * 0.3); - if (logoModules % 2 !== moduleCount % 2) { - logoModules += 1; + 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") 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") as CanvasRenderingContext2D; - ctx.fillStyle = "white"; - ctx.fillRect( - backgroundPosition, - backgroundPosition, - backgroundSize, - backgroundSize, - ); - ctx.drawImage(logoImage, logoPosition, logoPosition, logoSize, logoSize); }; diff --git a/utils/settings.ts b/utils/settings.ts index c2211ac..813099c 100644 --- a/utils/settings.ts +++ b/utils/settings.ts @@ -54,7 +54,7 @@ export type ImageFormat = (typeof IMAGE_FORMATS)[number]; export const settingsSchema = z.object({ format: z.enum(IMAGE_FORMATS).default("png"), - logo: z.enum(LOGOS), + logo: z.enum(LOGOS).optional(), content: z.string().min(1, "Required"), });