Extract SVGs size from viewBox attibute (#590)

This commit is contained in:
Fabian Mu 2022-03-02 15:59:54 +01:00 committed by GitHub
parent e43219ded8
commit 32203637f2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 48 additions and 1 deletions

View file

@ -51,6 +51,7 @@ import {
saveToFileSystem,
openAssetFromFileSystem,
fileToBase64,
fileToText,
getImageSizeFromSrc,
getVideoSizeFromSrc,
} from './data'
@ -2889,8 +2890,31 @@ export class TldrawApp extends StateManager<TDSnapshot> {
} else {
src = await fileToBase64(file)
}
if (typeof src === 'string') {
const size = isImage ? await getImageSizeFromSrc(src) : await getVideoSizeFromSrc(src)
let size = [0, 0]
if (isImage) {
// attempt to get actual svg size from viewBox attribute as
if (extension[0] == '.svg') {
let svgString: string | ArrayBuffer | null
let viewBoxAttribute: string | null
let viewBox: string[]
svgString = await fileToText(file)
viewBoxAttribute = this.getViewboxFromSVG(svgString)
if (viewBoxAttribute) {
viewBox = viewBoxAttribute.split(' ')
size[0] = parseFloat(viewBox[2])
size[1] = parseFloat(viewBox[3])
}
}
if (size == [0,0]) {
size = await getImageSizeFromSrc(src)
}
} else {
size = await getVideoSizeFromSrc(src)
}
const match = Object.values(this.document.assets).find(
(asset) => asset.type === assetType && asset.src === src
)
@ -2923,6 +2947,17 @@ export class TldrawApp extends StateManager<TDSnapshot> {
return this
}
private getViewboxFromSVG = (svgStr: string | ArrayBuffer | null) => {
const viewBoxRegex = /.*?viewBox=["'](-?[\d\.]+[, ]+-?[\d\.]+[, ][\d\.]+[, ][\d\.]+)["']/
if (typeof svgStr === 'string') {
const matches = svgStr.match(viewBoxRegex)
return matches && matches.length >= 2 ? matches[1] : null;
}
console.warn('could not get viewbox from svg string')
this.setIsLoading(false)
return null
}
/* -------------------------------------------------- */
/* Event Handlers */
/* -------------------------------------------------- */

View file

@ -129,6 +129,18 @@ export function fileToBase64(file: Blob): Promise<string | ArrayBuffer | null> {
})
}
export function fileToText(file: Blob): Promise<string | ArrayBuffer | null> {
return new Promise((resolve, reject) => {
if (file) {
const reader = new FileReader()
reader.readAsText(file)
reader.onload = () => resolve(reader.result)
reader.onerror = (error) => reject(error)
reader.onabort = (error) => reject(error)
}
})
}
export function getImageSizeFromSrc(src: string): Promise<number[]> {
return new Promise((resolve, reject) => {
const img = new Image()