diff --git a/src/editor/core/draw/particle/ImageParticle.ts b/src/editor/core/draw/particle/ImageParticle.ts
index c1af81e..b4d5324 100644
--- a/src/editor/core/draw/particle/ImageParticle.ts
+++ b/src/editor/core/draw/particle/ImageParticle.ts
@@ -1,5 +1,6 @@
import { IEditorOption } from '../../../interface/Editor'
import { IElement } from '../../../interface/Element'
+import { convertStringToBase64 } from '../../../utils'
import { Draw } from '../Draw'
export class ImageParticle {
@@ -18,6 +19,24 @@ export class ImageParticle {
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 = ``
+ 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) {
const { scale } = this.options
const width = element.width! * scale
@@ -36,6 +55,11 @@ export class ImageParticle {
resolve(element)
}
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)
}
})
diff --git a/src/editor/utils/index.ts b/src/editor/utils/index.ts
index c3e5834..c956df3 100644
--- a/src/editor/utils/index.ts
+++ b/src/editor/utils/index.ts
@@ -148,4 +148,12 @@ export function cloneProperty(properties: (keyof T)[], sourceElement: T, targ
delete targetElement[property]
}
}
+}
+
+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
}
\ No newline at end of file