feat: add fallback placeholder image
This commit is contained in:
@@ -1,5 +1,6 @@
|
|||||||
import { IEditorOption } from '../../../interface/Editor'
|
import { IEditorOption } from '../../../interface/Editor'
|
||||||
import { IElement } from '../../../interface/Element'
|
import { IElement } from '../../../interface/Element'
|
||||||
|
import { convertStringToBase64 } from '../../../utils'
|
||||||
import { Draw } from '../Draw'
|
import { Draw } from '../Draw'
|
||||||
|
|
||||||
export class ImageParticle {
|
export class ImageParticle {
|
||||||
@@ -18,6 +19,24 @@ export class ImageParticle {
|
|||||||
this.draw.getImageObserver().add(promise)
|
this.draw.getImageObserver().add(promise)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getFallbackImage(width: number, height: number): HTMLImageElement {
|
||||||
|
const tileSize = 8
|
||||||
|
const x = (width - Math.ceil(width / tileSize) * tileSize) / 2
|
||||||
|
const y = (height - Math.ceil(height / tileSize) * tileSize) / 2
|
||||||
|
const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="${width}" height="${height}" viewBox="0 0 ${width} ${height}">
|
||||||
|
<rect width="${width}" height="${height}" fill="url(#mosaic)" />
|
||||||
|
<defs>
|
||||||
|
<pattern id="mosaic" x="${x}" y="${y}" width="${tileSize * 2}" height="${tileSize * 2}" patternUnits="userSpaceOnUse">
|
||||||
|
<rect width="${tileSize}" height="${tileSize}" fill="#cccccc" />
|
||||||
|
<rect width="${tileSize}" height="${tileSize}" fill="#cccccc" transform="translate(${tileSize}, ${tileSize})" />
|
||||||
|
</pattern>
|
||||||
|
</defs>
|
||||||
|
</svg>`
|
||||||
|
const fallbackImage = new Image()
|
||||||
|
fallbackImage.src = `data:image/svg+xml;base64,${convertStringToBase64(svg)}`
|
||||||
|
return fallbackImage
|
||||||
|
}
|
||||||
|
|
||||||
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
public render(ctx: CanvasRenderingContext2D, element: IElement, x: number, y: number) {
|
||||||
const { scale } = this.options
|
const { scale } = this.options
|
||||||
const width = element.width! * scale
|
const width = element.width! * scale
|
||||||
@@ -36,6 +55,11 @@ export class ImageParticle {
|
|||||||
resolve(element)
|
resolve(element)
|
||||||
}
|
}
|
||||||
img.onerror = (error) => {
|
img.onerror = (error) => {
|
||||||
|
const fallbackImage = this.getFallbackImage(width, height)
|
||||||
|
fallbackImage.onload = () => {
|
||||||
|
ctx.drawImage(fallbackImage, x, y, width, height)
|
||||||
|
this.imageCache.set(element.id!, fallbackImage)
|
||||||
|
}
|
||||||
reject(error)
|
reject(error)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -149,3 +149,11 @@ export function cloneProperty<T>(properties: (keyof T)[], sourceElement: T, targ
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function convertStringToBase64(input: string) {
|
||||||
|
const encoder = new TextEncoder()
|
||||||
|
const data = encoder.encode(input)
|
||||||
|
const charArray = Array.from(data, byte => String.fromCharCode(byte))
|
||||||
|
const base64 = window.btoa(charArray.join(''))
|
||||||
|
return base64
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user