Skip to content

Commit 7c04e99

Browse files
committed
refactor: remove composable
Since it doesn't hold any state, it seems like it's better as a utility fn - we can always add it back if needed later
1 parent c3671ab commit 7c04e99

File tree

3 files changed

+48
-38
lines changed

3 files changed

+48
-38
lines changed

app/composables/useSvgToPng.ts

Lines changed: 0 additions & 35 deletions
This file was deleted.

app/pages/brand.vue

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ defineOgImageComponent('Default', {
1414
description: $t('brand.meta_description'),
1515
})
1616
17-
const { convert } = useSvgToPng()
18-
1917
const logos = [
2018
{
2119
name: () => $t('brand.logos.wordmark'),
@@ -45,7 +43,7 @@ async function handlePngDownload(logo: (typeof logos)[number]) {
4543
if (pngLoading.value.has(logo.src)) return
4644
pngLoading.value.add(logo.src)
4745
try {
48-
const blob = await convert(logo.src, logo.width, logo.height)
46+
const blob = await svgToPng(logo.src, logo.width, logo.height)
4947
const filename = logo.src.replace(/^\//, '').replace('.svg', '.png')
5048
downloadFile(blob, filename)
5149
} finally {

app/utils/svg.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/**
2+
* Convert an SVG (URL or data URI) into a PNG Blob.
3+
*
4+
* @param svgUrl - URL or data URI pointing to the SVG to convert. If remote,
5+
* the resource must be accessible (CORS allowed) for use in a canvas.
6+
* @param width - Desired logical width (CSS pixels) of the output image.
7+
* @param height - Desired logical height (CSS pixels) of the output image.
8+
* @param scale - Optional pixel scale multiplier (use 2 for high-DPI output). Default: 2.
9+
* @returns A Promise that resolves with a PNG Blob containing the rendered image.
10+
* @throws {Error} If the SVG fails to load or if the canvas cannot produce a Blob.
11+
*/
12+
export async function svgToPng(
13+
svgUrl: string,
14+
width: number,
15+
height: number,
16+
scale = 2,
17+
): Promise<Blob> {
18+
await document.fonts.ready
19+
20+
const img = new Image()
21+
img.crossOrigin = 'anonymous'
22+
23+
const loaded = new Promise<void>((resolve, reject) => {
24+
// oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)
25+
img.onload = () => resolve()
26+
// oxlint-disable-next-line eslint-plugin-unicorn(prefer-add-event-listener)
27+
img.onerror = () => reject(new Error(`Failed to load SVG: ${svgUrl}`))
28+
})
29+
30+
img.src = svgUrl
31+
await loaded
32+
33+
const canvas = document.createElement('canvas')
34+
canvas.width = width * scale
35+
canvas.height = height * scale
36+
37+
const ctx = canvas.getContext('2d')!
38+
ctx.scale(scale, scale)
39+
ctx.drawImage(img, 0, 0, width, height)
40+
41+
return new Promise<Blob>((resolve, reject) => {
42+
canvas.toBlob(blob => {
43+
if (blob) resolve(blob)
44+
else reject(new Error('Canvas toBlob failed'))
45+
}, 'image/png')
46+
})
47+
}

0 commit comments

Comments
 (0)