From ee14bccc9dedd53aa840e8f3f22c908a601a541a Mon Sep 17 00:00:00 2001 From: Iris Hoffmeyer Date: Sun, 29 Sep 2024 12:25:40 -0400 Subject: [PATCH 1/2] Use guard for clarity --- components/viewer/modal/BackpackModal.vue | 136 +++++++++++----------- 1 file changed, 69 insertions(+), 67 deletions(-) diff --git a/components/viewer/modal/BackpackModal.vue b/components/viewer/modal/BackpackModal.vue index 0153906..d1e8d38 100644 --- a/components/viewer/modal/BackpackModal.vue +++ b/components/viewer/modal/BackpackModal.vue @@ -143,79 +143,81 @@ const objectMode = computed(() => { const backpackRef = ref(); const isLoading = ref(false); const backpackToImage = async () => { - if (backpackRef.value && packRows.value.length >= 1) { - isLoading.value = true; - const $toast = useToast(); - const toastGenerateImage = $toast.info('Generating image...', { - timeout: false, - }); - // Wait for the next tick to ensure DOM is updated before getting the element. - await nextTick(); + if (packRows.value.length <= 0) { + alert( + 'No objects selected to create a backpack image, select at least one object to create a image.', + ); + return; + } + if (!backpackRef.value) return; - // Set background color for svg to project background color if it exists - const currentBackground = backpackRef.value.style.backgroundColor; - backpackRef.value.style.backgroundColor = - project?.data.styling.backgroundColor ?? currentBackground; - // Convert backpack to SVG - const svgDocument = elementToSVG(backpackRef.value); - // Inline external resources (fonts, images, etc) as data: URIs - await inlineResources(svgDocument.documentElement); - // Restore background color - backpackRef.value.style.backgroundColor = currentBackground; - // Get SVG string - const svgString = new XMLSerializer().serializeToString(svgDocument); - // Create a Blob from the SVG string - const svg = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' }); - // Create a downloadable link for img src - const svgUrl = URL.createObjectURL(svg); - const img = new Image(); - // set the image src to the URL of the Blob - img.src = svgUrl; - // Wait until the image has loaded - await img.decode(); - // Create a canvas to draw the image to - const canvas = document.createElement('canvas'); - // Set canvas dimensions to match the image - canvas.width = img.naturalWidth; - canvas.height = img.naturalHeight; - const ctx = canvas.getContext('2d')!; - // Draw the image to the canvas - ctx.drawImage(img, 0, 0); - // Get the image data as a PNG string - const url = canvas.toDataURL('image/png'); - // Remove the canvas - canvas.remove(); + isLoading.value = true; + const $toast = useToast(); + const toastGenerateImage = $toast.info('Generating image...', { + timeout: false, + }); + // Wait for the next tick to ensure DOM is updated before getting the element. + await nextTick(); - isLoading.value = false; - $toast.dismiss(toastGenerateImage); + // Set background color for svg to project background color if it exists + const currentBackground = backpackRef.value.style.backgroundColor; + backpackRef.value.style.backgroundColor = + project?.data.styling.backgroundColor ?? currentBackground; + // Convert backpack to SVG + const svgDocument = elementToSVG(backpackRef.value); + // Inline external resources (fonts, images, etc) as data: URIs + await inlineResources(svgDocument.documentElement); + // Restore background color + backpackRef.value.style.backgroundColor = currentBackground; + // Get SVG string + const svgString = new XMLSerializer().serializeToString(svgDocument); + // Create a Blob from the SVG string + const svg = new Blob([svgString], { type: 'image/svg+xml;charset=utf-8' }); + // Create a downloadable link for img src + const svgUrl = URL.createObjectURL(svg); + const img = new Image(); + // set the image src to the URL of the Blob + img.src = svgUrl; + // Wait until the image has loaded + await img.decode(); + // Create a canvas to draw the image to + const canvas = document.createElement('canvas'); + // Set canvas dimensions to match the image + canvas.width = img.naturalWidth; + canvas.height = img.naturalHeight; + const ctx = canvas.getContext('2d')!; + // Draw the image to the canvas + ctx.drawImage(img, 0, 0); + // Get the image data as a PNG string + const url = canvas.toDataURL('image/png'); + // Remove the canvas + canvas.remove(); - // Ensure the URL is valid before trying to download it - if (!url.startsWith('data:image/png')) { - $toast.error('Failed to generate backpack image.'); - console.log(url); - } else { - $toast.success('Backpack image generated'); - // Create a element to download the image - const element = document.createElement('a'); - // Set the download link href and download attribute - element.href = url; - element.download = `backpack-${new Date().toLocaleString()}.png`; + isLoading.value = false; + $toast.dismiss(toastGenerateImage); - // Click the link to download the image - await nextTick(() => { - element.click(); - }); - // Remove the element once downloaded - element.remove(); - } + // Ensure the URL is valid before trying to download it + if (!url.startsWith('data:image/png')) { + $toast.error('Failed to generate backpack image.'); + console.log(url); + } else { + $toast.success('Backpack image generated'); + // Create a element to download the image + const element = document.createElement('a'); + // Set the download link href and download attribute + element.href = url; + element.download = `backpack-${new Date().toLocaleString()}.png`; - // Clean up the URL after download - URL.revokeObjectURL(url); - } else if (packRows.value.length === 0) { - alert( - 'No objects selected to create a backpack image, select at least one object to create a image.', - ); + // Click the link to download the image + await nextTick(() => { + element.click(); + }); + // Remove the element once downloaded + element.remove(); } + + // Clean up the URL after download + URL.revokeObjectURL(url); }; From 07d822025fa210afd279875f1b4389d9a1055af6 Mon Sep 17 00:00:00 2001 From: Iris Hoffmeyer Date: Sun, 29 Sep 2024 13:05:42 -0400 Subject: [PATCH 2/2] Limit canvas size to max supported by browser --- components/viewer/modal/BackpackModal.vue | 19 ++++++++++++++++--- package.json | 2 ++ yarn.lock | 16 ++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/components/viewer/modal/BackpackModal.vue b/components/viewer/modal/BackpackModal.vue index d1e8d38..fff32fd 100644 --- a/components/viewer/modal/BackpackModal.vue +++ b/components/viewer/modal/BackpackModal.vue @@ -91,6 +91,7 @@