优化ImageKnifeComponent的ImageKnifeOption耗时
Signed-off-by: 张欢 <zhanghuan165@h-partners.com>
This commit is contained in:
parent
83075cc204
commit
77949e2b91
|
@ -9,6 +9,7 @@
|
|||
- 修改全局请求头覆盖request请求头
|
||||
- imageKnife支持heic测试demo独立页面展示
|
||||
- drawLifeCycle支持gif图
|
||||
- 优化ImageKnifeComponent的ImageKnifeOption耗时
|
||||
|
||||
## 2.1.2-rc.12
|
||||
- 新增gif播放次数功能
|
||||
|
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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 {
|
||||
ImageKnifeComponent,
|
||||
ImageKnifeOption,
|
||||
HeaderOptions,
|
||||
ImageKnifeOptionNext
|
||||
} from '@ohos/libraryimageknife'
|
||||
|
||||
|
||||
@Entry
|
||||
@Component
|
||||
struct IndexPerformance {
|
||||
@State headerOptions1: HeaderOptions = {
|
||||
key: "refer",
|
||||
value: "http://1.94.37.200:7070/AntiTheftChain/downloadImage"
|
||||
};
|
||||
@State imageKnifeOption1: ImageKnifeOptionNext =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
headerOption: [this.headerOptions1]
|
||||
};
|
||||
@State imageKnifeOption2: ImageKnifeOptionNext =
|
||||
{
|
||||
loadSrc: $r('app.media.icon'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
headerOption: [this.headerOptions1]
|
||||
};
|
||||
@State imageKnifeOption3: ImageKnifeOption =
|
||||
{
|
||||
loadSrc: $r('app.media.yunHeic'),
|
||||
placeholderSrc: $r('app.media.icon_loading'),
|
||||
errorholderSrc: $r('app.media.icon_failed'),
|
||||
};
|
||||
@State flag: boolean = true;
|
||||
|
||||
build() {
|
||||
Scroll() {
|
||||
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Text("简单示例1:加载一张本地png图片").fontSize(15)
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Button("加载PNG")
|
||||
.onClick(() => {
|
||||
this.imageKnifeOption1.loadSrc = $r('app.media.pngSample')
|
||||
|
||||
}).margin({ top: 5, left: 3 })
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
|
||||
}.width('100%').backgroundColor(Color.Pink)
|
||||
|
||||
Text("简单示例2:加载一张网络gif图片").fontSize(15)
|
||||
Text("gif解析在子线程,请在页面构建后创建worker,注入imageknife").fontSize(15)
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Button("加载GIF")
|
||||
.onClick(() => {
|
||||
this.imageKnifeOption2.loadSrc = 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658'
|
||||
|
||||
|
||||
}).margin({ top: 5, left: 3 })
|
||||
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300)
|
||||
}.width('100%').backgroundColor(Color.Pink)
|
||||
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
.height('100%')
|
||||
}
|
||||
|
||||
aboutToAppear() {
|
||||
|
||||
}
|
||||
|
||||
aboutToDisappear() {
|
||||
|
||||
}
|
||||
|
||||
onBackPress() {
|
||||
|
||||
}
|
||||
}
|
|
@ -396,6 +396,13 @@ struct IndexFunctionDemo {
|
|||
router.pushUrl({ url: 'pages/testImageKnifeHeic' });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
}.width('100%').height(60).backgroundColor(Color.Pink)
|
||||
Text('测试ImageKnifeOptionNext').fontSize(15)
|
||||
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
|
||||
Button('测试ImageKnifeOptionNext')
|
||||
.onClick(() => {
|
||||
router.pushUrl({ url: 'pages/IndexPerformance' });
|
||||
}).margin({ top: 5, left: 3 })
|
||||
}.width('100%').height(60).backgroundColor(Color.Pink)
|
||||
}
|
||||
}
|
||||
.width('100%')
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
"pages/webpImageTestPage",
|
||||
"pages/testStopPlayingGifPage",
|
||||
"pages/testImageKnifeDataFetch",
|
||||
"pages/testImageKnifeHeic"
|
||||
"pages/testImageKnifeHeic",
|
||||
"pages/IndexPerformance"
|
||||
]
|
||||
}
|
|
@ -110,6 +110,8 @@ export {IDataFetch} from './src/main/ets/components/imageknife/networkmanage/IDa
|
|||
export {ICache} from './src/main/ets/components/imageknife/requestmanage/ICache'
|
||||
export { FileTypeUtil } from './src/main/ets/components/imageknife/utils/FileTypeUtil'
|
||||
export { ParseImageUtil } from './src/main/ets/components/imageknife/utils/ParseImageUtil'
|
||||
export { ImageKnifeComponentNext } from './src/main/ets/components/imageknife/ImageKnifeComponentNext'
|
||||
export { ImageKnifeOptionNext } from './src/main/ets/components/imageknife/ImageKnifeOptionNext'
|
||||
|
||||
/**
|
||||
* svg parse
|
||||
|
|
|
@ -27,7 +27,6 @@ import { ObjectKey } from './ObjectKey'
|
|||
import componentUtils from '@ohos.arkui.componentUtils'
|
||||
import inspector from '@ohos.arkui.inspector'
|
||||
import util from '@ohos.util'
|
||||
import { ImageKnifeDrawFactory } from './ImageKnifeDrawFactory'
|
||||
|
||||
interface KeyCanvas {
|
||||
keyId:string
|
||||
|
@ -35,13 +34,14 @@ interface KeyCanvas {
|
|||
@Component
|
||||
export struct ImageKnifeComponent {
|
||||
@Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
|
||||
autoPlay: boolean = true
|
||||
private settings: RenderingContextSettings = new RenderingContextSettings(true)
|
||||
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
|
||||
private hasDisplayRetryholder = false;
|
||||
private lastWidth: number = 0
|
||||
private lastHeight: number = 0
|
||||
// 当前帧数位置
|
||||
private renderFrames_index = 0;
|
||||
@State currentWidth : number | string = "100%"
|
||||
@State currentHeight : number | string = "100%"
|
||||
// 定时器id
|
||||
private gifTimerId: number = -1
|
||||
// 完整gif播放时间
|
||||
|
@ -108,16 +108,12 @@ export struct ImageKnifeComponent {
|
|||
private lastSrc: string | Resource | PixelMap = ""
|
||||
listener: inspector.ComponentObserver = inspector.createComponentObserver(this.keyCanvas.keyId)
|
||||
|
||||
@State currentSize : Size = {
|
||||
width: 0.01,
|
||||
height: 0.01
|
||||
}
|
||||
|
||||
build() {
|
||||
Canvas(this.context)
|
||||
.key(this.keyCanvas.keyId)
|
||||
.width((this.imageKnifeOption!=undefined && this.imageKnifeOption.mainScaleType!= undefined && this.imageKnifeOption.mainScaleType == ScaleType.AUTO_WIDTH )? this.currentSize.width:'100%')
|
||||
.height((this.imageKnifeOption!=undefined && this.imageKnifeOption.mainScaleType!= undefined && this.imageKnifeOption.mainScaleType == ScaleType.AUTO_HEIGHT )? this.currentSize.height:'100%')
|
||||
.width(this.currentWidth)
|
||||
.height(this.currentHeight)
|
||||
.renderFit(RenderFit.RESIZE_FILL)
|
||||
.onReady(() => {
|
||||
let ctx = this.context;
|
||||
|
@ -416,7 +412,6 @@ export struct ImageKnifeComponent {
|
|||
}
|
||||
|
||||
displayMainSource = (data: ImageKnifeData|number|undefined)=> {
|
||||
ImageKnifeDrawFactory.type = undefined;
|
||||
if(data == undefined || typeof data == 'number'){
|
||||
return
|
||||
}
|
||||
|
@ -598,12 +593,12 @@ export struct ImageKnifeComponent {
|
|||
let scaleHeight = imageInfo.size.height/imageInfo.size.width
|
||||
let scaleWidth = imageInfo.size.width/imageInfo.size.height
|
||||
if (this.imageKnifeOption.mainScaleType == ScaleType.AUTO_WIDTH){
|
||||
this.currentSize.width=this.context.height*scaleWidth
|
||||
this.currentWidth=this.context.height*scaleWidth
|
||||
}else if (this.imageKnifeOption.mainScaleType == ScaleType.AUTO_HEIGHT){
|
||||
this.currentSize.height=this.context.width*scaleHeight
|
||||
this.currentHeight=this.context.width*scaleHeight
|
||||
}else if (this.imageKnifeOption.mainScaleType == ScaleType.AUTO){
|
||||
this.currentSize.height=imageInfo.size.height
|
||||
this.currentSize.width =imageInfo.size.width
|
||||
this.currentHeight=imageInfo.size.height
|
||||
this.currentWidth =imageInfo.size.width
|
||||
}
|
||||
ScaleTypeHelper.drawImageWithScaleType(context, scaleType, data.drawPixelMap?.imagePixelMap, px2vp(imageInfo.size.width), px2vp(imageInfo.size.height), compWidth, compHeight, 0, 0)
|
||||
context.restore();
|
||||
|
@ -767,15 +762,15 @@ export struct ImageKnifeComponent {
|
|||
let frames = data.drawGIFFrame?.imageGIFFrames as GIFFrame[]
|
||||
LogUtil.log('ImageKnifeComponent gifFrameLength =' + frames.length);
|
||||
if (imageKnifeOption.gif && (typeof (imageKnifeOption.gif.seekTo) == 'number') && imageKnifeOption.gif.seekTo >= 0) {
|
||||
this.autoPlay = false;
|
||||
context.clearRect(0, 0, compWidth, compHeight)
|
||||
this.drawSeekToFrame(frames, context, compWidth, compHeight)
|
||||
} else {
|
||||
this.autoPlay = true
|
||||
context.clearRect(0, 0, compWidth, compHeight)
|
||||
|
||||
this.renderFrames_frames = frames
|
||||
if (this.imageKnifeOption.autoPlay == undefined) {
|
||||
this.renderFrames_index = 0;
|
||||
}
|
||||
this.renderFrames_index = 0
|
||||
this.renderFrames_context = context
|
||||
this.renderFrames_compWidth = compWidth
|
||||
this.renderFrames_compHeight = compHeight
|
||||
|
@ -799,13 +794,13 @@ export struct ImageKnifeComponent {
|
|||
private drawSeekToFrame(frames: GIFFrame[], context: CanvasRenderingContext2D, compWidth: number, compHeight: number) {
|
||||
if(this.imageKnifeOption.gif != undefined && this.imageKnifeOption.gif.seekTo != undefined) {
|
||||
for (let i = 0; i < this.imageKnifeOption.gif.seekTo; i++) {
|
||||
this.renderFrames_index = i;
|
||||
this.drawFrame(frames, i, context, compWidth, compHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
renderFrames_frames: GIFFrame[] | undefined = undefined
|
||||
renderFrames_index: number = 0;
|
||||
renderFrames_context: CanvasRenderingContext2D | undefined = undefined;
|
||||
renderFrames_compWidth: number = 0;
|
||||
renderFrames_compHeight: number = 0
|
||||
|
@ -823,7 +818,7 @@ export struct ImageKnifeComponent {
|
|||
if (this.renderFrames_frames != undefined && this.renderFrames_index === (this.renderFrames_frames.length - 1) && this.imageKnifeOption.gif != undefined ) {
|
||||
this.playTimes++
|
||||
if (this.imageKnifeOption.gif.playTimes == this.playTimes){
|
||||
this.imageKnifeOption.autoPlay = false;
|
||||
this.autoPlay = false
|
||||
this.playTimes = 0
|
||||
}
|
||||
}
|
||||
|
@ -836,7 +831,7 @@ export struct ImageKnifeComponent {
|
|||
let end = new Date().getTime();
|
||||
let diff = end - start
|
||||
|
||||
if ((this.imageKnifeOption.autoPlay == undefined) || (this.imageKnifeOption.autoPlay)) {
|
||||
if (this.autoPlay) {
|
||||
|
||||
// 理论上该帧在屏幕上保留的时间
|
||||
let stayTime:number= 0
|
||||
|
@ -901,58 +896,10 @@ export struct ImageKnifeComponent {
|
|||
ScaleTypeHelper.drawImageWithScaleType(context, scaleType, pixelmap, px2vp(frameW), px2vp(frameH), compWidth, compHeight, px2vp(frame.dims.left), px2vp(frame.dims.top))
|
||||
// tips:worker如果不是在展示页面中创建,使用子线程回来的数据创建的图片,会导致canvas绘制不出来
|
||||
context.restore();
|
||||
if (ImageKnifeDrawFactory.type === undefined) {
|
||||
return;
|
||||
}
|
||||
// 通过 destination-in 裁剪出圆角
|
||||
if (ImageKnifeDrawFactory?.type === DrawType.Round || ImageKnifeDrawFactory?.type === DrawType.Oval) {
|
||||
context.save();
|
||||
context.globalCompositeOperation = 'destination-in';
|
||||
if (ImageKnifeDrawFactory.type === DrawType.Round) {
|
||||
ImageKnifeDrawFactory.setRect(context, scaleType, pixelmap, px2vp(frameW), px2vp(frameH), compWidth,
|
||||
compHeight, 0, 0, ImageKnifeDrawFactory.borderWidth, ImageKnifeDrawFactory.connerRadius);
|
||||
} else {
|
||||
context.beginPath();
|
||||
ImageKnifeDrawFactory.setOval(context, scaleType, pixelmap, px2vp(frameW), px2vp(frameH), compWidth,
|
||||
compHeight, 0, 0, ImageKnifeDrawFactory.borderWidth);
|
||||
context.closePath();
|
||||
}
|
||||
context.fill();
|
||||
context.restore();
|
||||
if (ImageKnifeDrawFactory.borderWidth > 0) {
|
||||
// 为圆角添加边框
|
||||
context.save();
|
||||
context.strokeStyle = ImageKnifeDrawFactory.colorString;
|
||||
context.lineWidth = ImageKnifeDrawFactory.borderWidth;
|
||||
context.globalCompositeOperation = 'source-over';
|
||||
if (ImageKnifeDrawFactory.type === DrawType.Round) {
|
||||
ImageKnifeDrawFactory.setRect(context, scaleType, pixelmap, px2vp(frameW), px2vp(frameH), compWidth,
|
||||
compHeight, 0, 0, ImageKnifeDrawFactory.borderWidth, ImageKnifeDrawFactory.connerRadius);
|
||||
} else {
|
||||
context.beginPath();
|
||||
ImageKnifeDrawFactory.setOval(context, scaleType, pixelmap, px2vp(frameW), px2vp(frameH), compWidth,
|
||||
compHeight, 0, 0, ImageKnifeDrawFactory.borderWidth);
|
||||
context.closePath();
|
||||
}
|
||||
context.stroke();
|
||||
context.restore();
|
||||
}
|
||||
context.restore();
|
||||
}
|
||||
LogUtil.log('ImageKnifeComponent canvasDrawPixelMap end!')
|
||||
}
|
||||
}
|
||||
|
||||
export enum DrawType{
|
||||
|
||||
Normal = 0,
|
||||
|
||||
Oval = 1,
|
||||
|
||||
Round = 2
|
||||
|
||||
}
|
||||
|
||||
export enum FrameDisposalType {
|
||||
// 0 - No disposal specified. The decoder is not required to take any action.
|
||||
// 不使用处置方法
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -69,8 +69,6 @@ export interface HeaderOptions {
|
|||
|
||||
@Observed
|
||||
export class ImageKnifeOption {
|
||||
//控制gif开关
|
||||
autoPlay?: boolean = true;
|
||||
// header请求列表
|
||||
headerOption?: Array<HeaderOptions>;
|
||||
// 主图资源
|
||||
|
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (C) 2021 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 { AUTOMATIC } from '../cache/diskstrategy/enum/AUTOMATIC'
|
||||
|
||||
import { DiskStrategy } from '../cache/diskstrategy/DiskStrategy'
|
||||
import { BaseTransform } from '../imageknife/transform/BaseTransform'
|
||||
import { TransformType } from '../imageknife/transform/TransformType'
|
||||
import { CropType } from '../imageknife/transform/CropTransformation'
|
||||
import { AllCacheInfo, IAllCacheInfoCallback } from '../imageknife/interface/IAllCacheInfoCallback'
|
||||
import { IDrawLifeCycle } from '../imageknife/interface/IDrawLifeCycle'
|
||||
import { ScaleType } from '../imageknife/ImageKnifeComponent'
|
||||
import { rgbColor } from './transform/CropCircleWithBorderTransformation'
|
||||
import { RoundCorner } from './transform/RoundedCornersTransformation'
|
||||
import { ObjectKey } from './ObjectKey'
|
||||
import common from '@ohos.app.ability.common'
|
||||
import { Priority } from './RequestOption'
|
||||
|
||||
export interface CropCircleWithBorder{
|
||||
border: number,
|
||||
obj: rgbColor
|
||||
}
|
||||
|
||||
export interface Crop{
|
||||
width: number,
|
||||
height: number,
|
||||
cropType: CropType
|
||||
}
|
||||
export interface BlurType {
|
||||
radius: number,
|
||||
sampling: number
|
||||
}
|
||||
export interface GifOptions{
|
||||
loopFinish?: (loopTime?:number) => void
|
||||
speedFactory?: number
|
||||
seekTo?: number
|
||||
playTimes?: number
|
||||
}
|
||||
export interface TransformOptions{
|
||||
transformType: number,
|
||||
blur?: BlurType,
|
||||
roundedCorners?: RoundCorner
|
||||
cropCircleWithBorder?: CropCircleWithBorder
|
||||
crop?:Crop
|
||||
brightnessFilter?: number,
|
||||
contrastFilter?: number,
|
||||
pixelationFilter?: number,
|
||||
swirlFilter?: number,
|
||||
mask?: Resource,
|
||||
rotateImage?: number
|
||||
}
|
||||
|
||||
export interface HeaderOptions {
|
||||
key: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
@Observed
|
||||
export class ImageKnifeOptionNext {
|
||||
// header请求列表
|
||||
headerOption?: Array<HeaderOptions>;
|
||||
// 主图资源
|
||||
@Track
|
||||
loadSrc: string | PixelMap | Resource = '';
|
||||
mainScaleType?: ScaleType = ScaleType.FIT_CENTER
|
||||
// 优先级
|
||||
priority?: Priority = Priority.MEDIUM
|
||||
enableGpu?:boolean = true;
|
||||
|
||||
// 磁盘缓存策略
|
||||
strategy?: DiskStrategy = new AUTOMATIC();
|
||||
|
||||
// gif加载展示一帧
|
||||
dontAnimateFlag? = false;
|
||||
|
||||
// 占位图
|
||||
placeholderSrc?: PixelMap | Resource;
|
||||
placeholderScaleType?: ScaleType = ScaleType.FIT_CENTER
|
||||
|
||||
// 失败占位图
|
||||
errorholderSrc?: PixelMap | Resource;
|
||||
errorholderSrcScaleType?: ScaleType = ScaleType.FIT_CENTER
|
||||
|
||||
// 重试占位图
|
||||
retryholderSrc?: Resource;
|
||||
retryholderScaleType?: ScaleType = ScaleType.FIT_CENTER
|
||||
|
||||
// 缩略图,范围(0,1)
|
||||
thumbSizeMultiplier?: number;
|
||||
// 缩略图展示时间
|
||||
thumbSizeDelay?:number;
|
||||
// 缩略图展示类型
|
||||
thumbSizeMultiplierScaleType?: ScaleType = ScaleType.FIT_CENTER
|
||||
|
||||
// 进度条
|
||||
displayProgress?: boolean;
|
||||
|
||||
|
||||
// 自定义缓存关键字
|
||||
signature?: ObjectKey;
|
||||
|
||||
// 重试图层 可点击
|
||||
canRetryClick?: boolean;
|
||||
|
||||
// 仅使用缓存加载数据
|
||||
onlyRetrieveFromCache?: boolean = false;
|
||||
|
||||
// 是否开启一级内存缓存
|
||||
isCacheable?: boolean = true;
|
||||
|
||||
|
||||
// 用户自定义实现 绘制方案
|
||||
drawLifeCycle?: IDrawLifeCycle;
|
||||
|
||||
// 设置点击事件回调
|
||||
onClick?:(event?: ClickEvent) => void
|
||||
|
||||
gif?: GifOptions = undefined;
|
||||
|
||||
|
||||
// 变换相关 不推荐使用该接口 建议直接使用transformation transformations这2个接口实现
|
||||
transform?:TransformOptions = undefined
|
||||
transformation?: BaseTransform<PixelMap>;
|
||||
transformations?: Array<BaseTransform<PixelMap>>;
|
||||
|
||||
// 输出缓存相关内容和信息
|
||||
allCacheInfoCallback?: IAllCacheInfoCallback;
|
||||
|
||||
|
||||
context?: common.UIAbilityContext;
|
||||
// sizeAnimate?: AnimateParam 由业务自定义不再支持
|
||||
|
||||
constructor() {
|
||||
|
||||
}
|
||||
}
|
|
@ -110,6 +110,8 @@ export {IDataFetch} from '@ohos/imageknife'
|
|||
export {ICache} from '@ohos/imageknife'
|
||||
export { FileTypeUtil } from '@ohos/imageknife'
|
||||
export { ParseImageUtil } from '@ohos/imageknife'
|
||||
export { ImageKnifeComponentNext} from '@ohos/imageknife'
|
||||
export { ImageKnifeOptionNext} from '@ohos/imageknife'
|
||||
|
||||
/**
|
||||
* svg parse
|
||||
|
|
Loading…
Reference in New Issue