From edb90750e67b7da5ef3397c5fe70bb01ff17d5f7 Mon Sep 17 00:00:00 2001 From: lyqht Date: Wed, 23 Oct 2024 09:53:08 +0800 Subject: [PATCH] fix border radius not respected for svg output --- src/App.vue | 27 +++++++++++++++---- src/utils/convertToImage.ts | 54 +++++++++++++++++++++++++++---------- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/App.vue b/src/App.vue index f76c3b0..84ef3c4 100644 --- a/src/App.vue +++ b/src/App.vue @@ -6,7 +6,6 @@ import { downloadPngElement, downloadSvgElement, getPngElement, - getSvgElement, getSvgString, IS_COPY_IMAGE_TO_CLIPBOARD_SUPPORTED } from '@/utils/convertToImage' @@ -228,7 +227,12 @@ function downloadQRImageAsPng() { if (exportMode.value === ExportMode.Single) { const qrCode = document.querySelector('#qr-code-container') if (qrCode) { - downloadPngElement(qrCode as HTMLElement, 'qr-code.png', options.value) + downloadPngElement( + qrCode as HTMLElement, + 'qr-code.png', + options.value, + styledBorderRadiusFormatted.value + ) } } else { generateBatchQRCodes('png') @@ -239,7 +243,12 @@ function downloadQRImageAsSvg() { if (exportMode.value === ExportMode.Single) { const qrCode = document.querySelector('#qr-code-container') if (qrCode) { - downloadSvgElement(qrCode as HTMLElement, 'qr-code.svg', options.value) + downloadSvgElement( + qrCode as HTMLElement, + 'qr-code.svg', + options.value, + styledBorderRadiusFormatted.value + ) } } else { generateBatchQRCodes('svg') @@ -494,9 +503,17 @@ async function generateBatchQRCodes(format: 'png' | 'svg') { await sleep(1000) let dataUrl: string = '' if (format === 'png') { - dataUrl = await getPngElement(qrCode as HTMLElement, options.value) + dataUrl = await getPngElement( + qrCode as HTMLElement, + options.value, + styledBorderRadiusFormatted.value + ) } else { - dataUrl = await getSvgString(qrCode as HTMLElement, options.value) + dataUrl = await getSvgString( + qrCode as HTMLElement, + options.value, + styledBorderRadiusFormatted.value + ) } createZipFile(zip, dataUrl, index, format) numQrCodesCreated++ diff --git a/src/utils/convertToImage.ts b/src/utils/convertToImage.ts index 2a22388..d7244c3 100644 --- a/src/utils/convertToImage.ts +++ b/src/utils/convertToImage.ts @@ -6,11 +6,15 @@ const defaultOptions: Options = { height: 400 } -const getFormattedOptions = (element: HTMLElement, options: Options): Options => { +const getFormattedOptions = ( + element: HTMLElement, + options: Options, + borderRadius?: string +): Options => { if (options.width && options.height) { const scale = getResizeScaleToFit(element, options.width, options.height) return { - style: { scale, transformOrigin: 'left top', borderRadius: '48px' }, + style: { scale, transformOrigin: 'left top', borderRadius: borderRadius ?? '48px' }, quality: 100, ...options } @@ -32,9 +36,13 @@ const getResizeScaleToFit = (child: HTMLElement, width: number, height: number): export const IS_COPY_IMAGE_TO_CLIPBOARD_SUPPORTED = navigator.clipboard && navigator.clipboard.write != undefined -export async function copyImageToClipboard(element: HTMLElement, options: Options) { +export async function copyImageToClipboard( + element: HTMLElement, + options: Options, + borderRadius?: string +) { if (IS_COPY_IMAGE_TO_CLIPBOARD_SUPPORTED) { - const formattedOptions = getFormattedOptions(element, options) + const formattedOptions = getFormattedOptions(element, options, borderRadius) console.debug('Converting to blob') domtoimage.toBlob(element, formattedOptions).then((blob: Blob) => { const item = new ClipboardItem({ [blob.type]: blob }) @@ -50,13 +58,18 @@ export async function copyImageToClipboard(element: HTMLElement, options: Option } } -export function getPngElement(element: HTMLElement, options: Options) { - const formattedOptions = getFormattedOptions(element, options) +export function getPngElement(element: HTMLElement, options: Options, borderRadius?: string) { + const formattedOptions = getFormattedOptions(element, options, borderRadius) return domtoimage.toPng(element, formattedOptions) } -export function downloadPngElement(element: HTMLElement, filename: string, options: Options) { - getPngElement(element, options) +export function downloadPngElement( + element: HTMLElement, + filename: string, + options: Options, + borderRadius?: string +) { + getPngElement(element, options, borderRadius) .then((dataUrl: string) => { const link = document.createElement('a') link.href = dataUrl @@ -79,23 +92,36 @@ function applySvgOptions(svgDocument: Document, options: Options) { } } -export async function getSvgString(element: HTMLElement, options: Options): Promise { - const formattedOptions = getFormattedOptions(element, options) +export async function getSvgString( + element: HTMLElement, + options: Options, + borderRadius?: string +): Promise { + const formattedOptions = getFormattedOptions(element, options, borderRadius) const svgDocument = elementToSVG(element) await inlineResources(svgDocument.documentElement) applySvgOptions(svgDocument, formattedOptions) return new XMLSerializer().serializeToString(svgDocument) } -export async function getSvgElement(element: HTMLElement, options: Options): Promise { - const svgString = await getSvgString(element, options) +export async function getSvgElement( + element: HTMLElement, + options: Options, + borderRadius?: string +): Promise { + const svgString = await getSvgString(element, options, borderRadius) // Convert SVG string to data URL return `data:image/svg+xml;charset=utf-8,${encodeURIComponent(svgString)}` } -export function downloadSvgElement(element: HTMLElement, filename: string, options: Options) { - getSvgElement(element, options) +export function downloadSvgElement( + element: HTMLElement, + filename: string, + options: Options, + borderRadius?: string +) { + getSvgElement(element, options, borderRadius) .then((dataUrl: string) => { const link = document.createElement('a') link.href = dataUrl