feat:web Add image placeholder

This commit is contained in:
wangxiangyuan
2023-08-28 12:01:27 +08:00
committed by osborn
parent e198c92530
commit 0c83159523
4 changed files with 177 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
import { DoricViewNode, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString } from "./DoricViewNode";
import { toRGBAString } from "../utils/color";
import { DoricViewNode, LEFT, RIGHT, CENTER_X, CENTER_Y, TOP, BOTTOM, toPixelString } from './DoricViewNode'
import { toRGBAString } from '../utils/color'
enum ScaleType {
ScaleToFill = 0,
@@ -8,6 +8,13 @@ enum ScaleType {
}
export class DoricImageNode extends DoricViewNode {
onloadFuncId?: string
placeHolderImage?: string
placeHolderImageBase64?: string
placeHolderColor?: number
errorImage?: string
errorImageBase64?: string
errorColor?: number
build(): HTMLElement {
const ret = document.createElement('img')
@@ -15,21 +22,31 @@ export class DoricImageNode extends DoricViewNode {
return ret
}
blend(props: { [index: string]: any }): void {
this.placeHolderImage = props['placeHolderImage']
this.placeHolderImageBase64 = props['placeHolderImageBase64']
this.placeHolderColor = props['placeHolderColor']
this.errorImage = props['errorImage']
this.errorImageBase64 = props['errorImageBase64']
this.errorColor = props['errorColor']
super.blend(props)
}
blendProps(v: HTMLImageElement, propName: string, prop: any) {
switch (propName) {
case 'imageUrl':
v.setAttribute('src', prop)
break
case 'imageBase64':
v.setAttribute('src', prop)
this.loadIntoTarget(v, prop)
break
case 'placeHolderImage':
case 'placeHolderImageBase64':
case 'placeHolderColor':
case 'errorImage':
case 'errorImageBase64':
case 'errorColor':
break
case 'loadCallback':
v.onload = () => {
this.callJSResponse(prop, {
width: v.width,
height: v.height
})
}
this.onloadFuncId = prop
break
case 'scaleType':
switch (prop) {
@@ -57,4 +74,65 @@ export class DoricImageNode extends DoricViewNode {
}
}
}
private loadIntoTarget(v: HTMLImageElement, src: any) {
let placeHolderSrc = ''
if (this.placeHolderImage) {
placeHolderSrc = v.src = this.placeHolderImage
} else if (this.placeHolderImageBase64) {
placeHolderSrc = v.src = this.placeHolderImageBase64
} else if (this.placeHolderColor) {
v.style.backgroundColor = toRGBAString(this.placeHolderColor)
}
v.onload = () => {
if (this.placeHolderColor) {
v.style.removeProperty('background-color')
}
if (this.onloadFuncId) {
this.callJSResponse(this.onloadFuncId, {
width: v.width,
height: v.height,
})
}
}
v.onerror = () => {
const error = this.getError(v.offsetWidth, v.offsetHeight)
if (!error) return
const same = src === error
const srcLoadError = v.src === src
if (same || !srcLoadError) return
v.src = error
}
setTimeout(() => {
v.src = src
})
}
private getError(width: number, height: number) {
if (this.errorImage) {
return this.errorImage
} else if (this.errorImageBase64) {
return this.errorImageBase64
} else if (this.errorColor && this.view) {
return this.createColoredCanvas(
width, height,
this.errorColor
)
}
return null
}
private createColoredCanvas(width: number, height: number, color: number) {
const canvas = document.createElement('canvas')
canvas.width = width
canvas.height = height
const context = canvas.getContext('2d')
if (context) {
context.fillStyle = toRGBAString(color)
context.fillRect(0, 0, width, height)
return canvas.toDataURL('image/png')
}
return null
}
}