forked from goplus/builder
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Improve compatibility & performance for svg in spx v1
- Loading branch information
Showing
4 changed files
with
74 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,64 @@ | ||
import { Disposable } from '@/utils/disposable' | ||
|
||
/** Convert arbitrary-type (supported by current browser) image content to type-`image/jpeg` content. */ | ||
export async function toJpeg(blob: Blob) { | ||
/** Convert arbitrary-type (supported by current browser) image content to another type. */ | ||
export function convertImg( | ||
/** Input image */ | ||
input: Blob, | ||
/** Mime type of the output image, see details in https://developer.mozilla.org/en-US/docs/Web/API/HTMLCanvasElement/toBlob#type */ | ||
type: string | ||
) { | ||
const d = new Disposable() | ||
return new Promise<Blob>((resolve, reject) => { | ||
const img = new Image() | ||
img.onload = () => { | ||
img.onload = async () => { | ||
const canvas = document.createElement('canvas') | ||
canvas.width = img.naturalWidth | ||
canvas.height = img.naturalHeight | ||
canvas.getContext('2d')?.drawImage(img, 0, 0) | ||
if (input.type === 'image/svg+xml') { | ||
const svgText = await input.text() | ||
const { width, height } = await getSVGSize(svgText) | ||
canvas.width = width | ||
canvas.height = height | ||
} else { | ||
canvas.width = img.naturalWidth | ||
canvas.height = img.naturalHeight | ||
} | ||
canvas.getContext('2d')?.drawImage(img, 0, 0, canvas.width, canvas.height) | ||
canvas.toBlob((newBlob) => { | ||
if (newBlob == null) { | ||
reject(new Error('toBlob failed')) | ||
return | ||
} | ||
resolve(newBlob) | ||
}, 'image/jpeg') | ||
}, type) | ||
} | ||
img.onerror = (e) => reject(new Error(`load image failed: ${e.toString()}`)) | ||
const url = URL.createObjectURL(blob) | ||
const url = URL.createObjectURL(input) | ||
d.addDisposer(() => URL.revokeObjectURL(url)) | ||
img.src = url | ||
}).finally(() => { | ||
d.dispose() | ||
}) | ||
} | ||
|
||
/** Convert arbitrary-type (supported by current browser) image content to type-`image/jpeg` content. */ | ||
export function toJpeg(blob: Blob) { | ||
return convertImg(blob, 'image/jpeg') | ||
} | ||
|
||
/** Convert arbitrary-type (supported by current browser) image content to type-`image/png` content. */ | ||
export async function toPng(blob: Blob) { | ||
return convertImg(blob, 'image/png') | ||
} | ||
|
||
/** Get the size of the SVG image, keeping consistent with spx. */ | ||
export async function getSVGSize(svgText: string) { | ||
const parser = new DOMParser() | ||
const svg = parser.parseFromString(svgText, 'image/svg+xml').documentElement | ||
if (!(svg instanceof SVGSVGElement)) throw new Error('invalid svg') | ||
// Keep consistent with spx, for details see: | ||
// * https://github.com/goplus/spx/blob/15b2e572746f3aaea519c2d9c0027188b50b62c8/internal/svgr/svg.go#L39 | ||
// * https://github.com/qiniu/oksvg/blob/917f53935572252ba3da8909ca4fbedec418bde1/svgd.go#L1015-L1049 | ||
let { width, height } = svg.viewBox.baseVal | ||
if (width === 0) width = svg.width.baseVal.value | ||
if (height === 0) height = svg.height.baseVal.value | ||
return { width, height } | ||
} |