168 lines
7.9 KiB
Plaintext
168 lines
7.9 KiB
Plaintext
/*
|
||
* Copyright (C) 2024 Huawei Device Co., Ltd.
|
||
* Licensed under the Apache License, Version 2.0 (the 'License');
|
||
* you may not use this file except in compliance with the License.
|
||
* You may obtain a copy of the License at
|
||
*
|
||
* http://www.apache.org/licenses/LICENSE-2.0
|
||
*
|
||
* Unless required by applicable law or agreed to in writing, software
|
||
* distributed under the License is distributed on an 'AS IS' BASIS,
|
||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
* See the License for the specific language governing permissions and
|
||
* limitations under the License.
|
||
*/
|
||
import { ImageKnifeOption } from '../model/ImageKnifeOption';
|
||
import { ImageKnifeRequest, ImageKnifeRequestState } from '../model/ImageKnifeRequest';
|
||
import common from '@ohos.app.ability.common';
|
||
import { ImageKnife } from '../ImageKnife';
|
||
import { LogUtil } from '../utils/LogUtil';
|
||
import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData';
|
||
import { IEngineKey } from '../key/IEngineKey';
|
||
import { DefaultEngineKey } from '../key/DefaultEngineKey';
|
||
|
||
@ComponentV2
|
||
export struct ImageKnifeComponent {
|
||
@Local pixelMap: PixelMap | string | undefined = undefined
|
||
@Param syncLoad: boolean = false
|
||
@Local adaptiveWidth: Length = '100%'
|
||
@Local adaptiveHeight: Length = '100%'
|
||
@Local objectFit: ImageFit = ImageFit.Contain
|
||
private request: ImageKnifeRequest | undefined
|
||
private lastWidth: number = 0
|
||
private lastHeight: number = 0
|
||
private currentWidth: number = 0
|
||
private currentHeight: number = 0
|
||
private componentVersion: number = 0
|
||
private currentContext: common.UIAbilityContext | undefined = undefined
|
||
@Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption();
|
||
|
||
@Monitor('imageKnifeOption',
|
||
"imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit",'imageKnifeOption.downsampleOf')
|
||
watchImageKnifeOption() {
|
||
this.clearLastRequest()
|
||
this.componentVersion++
|
||
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||
LogUtil.log("watchImageKnifeOption execute request:width=" + this.currentWidth + " height= " + this.currentHeight
|
||
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc
|
||
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc
|
||
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc)
|
||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
||
}
|
||
|
||
aboutToAppear(): void {
|
||
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||
|
||
if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题,建议使用同步方式在aboutToAppear时加载图片
|
||
let engineKey: IEngineKey = new DefaultEngineKey();
|
||
let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
|
||
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
|
||
if (memoryCacheSrc !== undefined){
|
||
LogUtil.log("aboutToAppear success load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc)
|
||
this.pixelMap = memoryCacheSrc.source;
|
||
}else{
|
||
LogUtil.log("aboutToAppear fail load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc)
|
||
if (this.imageKnifeOption.placeholderSrc !== undefined){
|
||
let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance()
|
||
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption))
|
||
if (memoryCachePlace !== undefined){
|
||
LogUtil.log("aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc)
|
||
this.pixelMap = memoryCachePlace.source;
|
||
}else{
|
||
LogUtil.log("aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
aboutToDisappear(): void {
|
||
this.clearLastRequest()
|
||
}
|
||
|
||
aboutToRecycle() {
|
||
this.clearLastRequest()
|
||
}
|
||
|
||
/**
|
||
* 对已DESTROY的组件不再发起请求
|
||
*/
|
||
private clearLastRequest(){
|
||
if (this.request !== undefined) {
|
||
this.request.requestState = ImageKnifeRequestState.DESTROY
|
||
this.request = undefined
|
||
}
|
||
}
|
||
|
||
build() {
|
||
Image(this.pixelMap)
|
||
.colorFilter(this.imageKnifeOption.drawingColorFilter)
|
||
.objectFit(this.objectFit)
|
||
.width(this.adaptiveWidth)
|
||
.height(this.adaptiveHeight)
|
||
.border(this.imageKnifeOption.border)
|
||
.syncLoad(this.syncLoad)
|
||
.draggable(false)
|
||
.onComplete(this.imageKnifeOption.onComplete)
|
||
.onSizeChange((oldValue:SizeOptions, newValue:SizeOptions) => {
|
||
this.currentWidth = newValue.width as number
|
||
this.currentHeight = newValue.height as number
|
||
this.lastWidth = oldValue.width as number
|
||
this.lastHeight = oldValue.height as number
|
||
|
||
// 条件1: 宽高值均有效,值>0. 条件2:当前宽高与上一次宽高不同
|
||
if (this.currentWidth > 0 && this.currentHeight > 0 &&
|
||
(this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth)) {
|
||
LogUtil.log("onSizeChange execute request:width=" + this.currentWidth + " height= " + this.currentHeight
|
||
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc
|
||
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc
|
||
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc)
|
||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
||
}
|
||
})
|
||
}
|
||
|
||
getCurrentContext(): common.UIAbilityContext {
|
||
if (this.currentContext == undefined) {
|
||
this.currentContext = getContext(this) as common.UIAbilityContext
|
||
}
|
||
return this.currentContext
|
||
}
|
||
|
||
getRequest(width: number, height: number): ImageKnifeRequest {
|
||
if (this.request == undefined) {
|
||
this.request = new ImageKnifeRequest(
|
||
this.imageKnifeOption,
|
||
this.imageKnifeOption.context !== undefined ? this.imageKnifeOption.context : this.getCurrentContext(),
|
||
width,
|
||
height,
|
||
this.componentVersion,
|
||
{
|
||
showPixelMap: async (version: number, pixelMap: PixelMap | string, requestSource: ImageKnifeRequestSource) => {
|
||
if (version !== this.componentVersion) {
|
||
return //针对reuse场景,不显示历史图片
|
||
}
|
||
this.pixelMap = pixelMap
|
||
if (typeof this.pixelMap !== 'string' && this.imageKnifeOption.objectFit === ImageFit.Auto) { //针对静态图高度自适应
|
||
let info = await this.pixelMap.getImageInfo()
|
||
this.adaptiveWidth = this.currentWidth
|
||
this.adaptiveHeight = info.size.height * this.currentWidth / info.size.width
|
||
}
|
||
|
||
if (requestSource == ImageKnifeRequestSource.SRC) {
|
||
this.objectFit =
|
||
this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
|
||
} else if (requestSource == ImageKnifeRequestSource.PLACE_HOLDER) {
|
||
this.objectFit =
|
||
this.imageKnifeOption.placeholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.placeholderObjectFit
|
||
} else {
|
||
this.objectFit =
|
||
this.imageKnifeOption.errorholderObjectFit === undefined ? (this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit) : this.imageKnifeOption.errorholderObjectFit
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
return this.request
|
||
}
|
||
} |