feat:web Add image placeholder
This commit is contained in:
		| @@ -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 | ||||
|     } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user