forked from floraachy/ImageKnife
181 lines
8.2 KiB
Plaintext
181 lines
8.2 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';
|
||
|
||
@Component
|
||
export struct ImageKnifeComponent {
|
||
@Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
|
||
@State pixelMap: PixelMap | string | undefined = undefined
|
||
@State syncLoad: boolean = false
|
||
@State adaptiveWidth: Length = '100%'
|
||
@State adaptiveHeight: Length = '100%'
|
||
@State 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
|
||
|
||
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
|
||
if (this.currentWidth <= 0 || this.currentHeight <= 0) {
|
||
// 存在宽或者高为0,此次重回无意义,无需进行request请求
|
||
} else {
|
||
// 前提:宽高值均有效,值>0. 条件1:当前宽高与上一次宽高不同 条件2:当前是第一次绘制
|
||
if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
|
||
LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight)
|
||
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
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))
|
||
}
|
||
|
||
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') {
|
||
if (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 (this.currentWidth / this.currentHeight > info.size.width / info.size.height) {
|
||
// this.adaptiveWidth = this.currentWidth
|
||
// this.adaptiveHeight = info.size.height * this.currentWidth / this.currentHeight
|
||
// }
|
||
// else {
|
||
// this.adaptiveWidth = info.size.width * this.currentWidth / this.currentHeight
|
||
// this.adaptiveHeight = this.currentHeight
|
||
// }
|
||
}
|
||
} else {
|
||
//console.info("KKKKKKKKKKK:" + pixelMap)
|
||
}
|
||
|
||
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
|
||
}
|
||
}
|
||
|
||
interface KeyCanvas {
|
||
keyId: string
|
||
} |