Revert "ComponentV2装饰器适配"

Signed-off-by: zgf <zenggaofeng2@h-partners.com>
This commit is contained in:
zgf 2024-09-27 16:40:57 +08:00
parent 1699f1bcd7
commit c99b3da4e7
32 changed files with 512 additions and 653 deletions

View File

@ -1,27 +1,17 @@
## 3.0.2
## 3.1.1-rc.0 - ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件
- 重构代码抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中降低函数复杂度 - 文件缓存数量负数和超过INT最大值时默认为INT最大值
- 修复宽高不等svg图片显示有毛边
## 3.1.0
- 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别 - 部分静态webp图片有delay属性导致识别成动图,改用getFrameCount识别
- 修复加载错误图后未去请求排队队列中的请求 - 修复加载错误图后未去请求排队队列中的请求
- 子线程本地Resource参数类型转换成number - 子线程本地Resource参数类型转换成number
- 修改使用hilog记录日志默认打开debug级别的日志 - 修改使用hilog记录日志默认打开debug级别的日志
- file格式图片fd同步close
- 解码pixelMap默认不可编辑图形变化可编辑 - 解码pixelMap默认不可编辑图形变化可编辑
- 修改网络请求超时设置 - 修改网络请求超时设置
- 重构代码抽取ImageKnifeDispatcher子线程requestJob相关代码到ImageKnifeLoader中降低函数复杂度
## 3.1.0-rc.2 ## 3.0.2-rc.0
- 修复宽高不等svg图片显示有毛边 - FileUtil.readFile接口和file格式图片同步关闭fd
## 3.1.0-rc.1
- ImageKnifeAnimatorComponent新增开始、结束、暂停的回调事件
- 文件缓存数量负数和超过INT最大值时默认为INT最大值
## 3.1.0-rc.0
- ComponentV2装饰器适配
- imageKnifeOption={...}用法改为new ImageKnifeOption({...})
- animatorOption={...}用法改为new AnimatorOption({...})
## 3.0.1 ## 3.0.1
- 修复animatorOption属性设置初始化值失效 - 修复animatorOption属性设置初始化值失效

344
README.md
View File

@ -1,228 +1,229 @@
# ImageKnife # ImageKnife
ImageKnife is a specially crafted image loading and caching library for OpenHarmony, optimized for efficiency, lightness, and simplicity. **专门为OpenHarmony打造的一款图像加载缓存库致力于更高效、更轻便、更简单。**
## Introduction ## 简介
This project is a self-developed version for OpenHarmony, inspired by the open-source [Glide](https://github.com/bumptech/glide) library. It sports the following features: 本项目参考开源库 [Glide](https://github.com/bumptech/glide) 进行OpenHarmony的自研版本
- Customizable memory cache strategy with adjustable cache size (default LRU) - 支持自定义内存缓存策略,支持设置内存缓存的大小(默认LRU策略)。
- Disk L2 cache for downloaded images - 支持磁盘二级缓存,对于下载图片会保存一份至磁盘当中。
- Custom implementation for image acquisition and network downloading - 支持自定义实现图片获取/网络下载
- Listening for progress of network downloads through callbacks - 支持监听网络下载回调进度
- Image options for borders and rounded corners - 继承Image的能力支持option传入border设置边框圆角
- Image scaling with **objectFit**, including auto-adapting height - 继承Image的能力支持option传入objectFit设置图片缩放包括objectFit为auto时根据图片自适应高度
- Image scaling through transformation - 支持通过设置transform缩放图片
- Concurrent request management with priority queuing - 并发请求数量,支持请求排队队列的优先级
- No requests made for images whose lifecycle has been destroyed - 支持生命周期已销毁的图片,不再发起请求
- Custom cache keys - 自定义缓存key
- Custom HTTP request headers - 自定义http网络请求头
- **writeCacheStrategy** for controlling cache storage (memory or file) - 支持writeCacheStrategy控制缓存的存入策略(只存入内存或文件缓存)
- Preloading images with **preLoadCache** - 支持preLoadCache预加载图片
- Loading images exclusively from cache with **onlyRetrieveFromCache** - 支持onlyRetrieveFromCache仅用缓存加载
- Support for image transformations such as blurring and highlighting - 支持使用一个或多个图片变换,如模糊,高亮等
Planned features: 待实现特性
- Memory downsampling optimization to save memory usage - gif/webp动图显示与控制
- Support for custom image decoding - 内存降采样优化,节约内存的占用
- 支持自定义图片解码
Note: The 3.x version has been significantly restructured from the 2.x version, mainly in the following aspects: 注意3.x版本相对2.x版本做了重大的重构主要体现在
- Use of the **Image** component instead of the **Canvas** component for rendering - 使用Image组件代替Canvas组件渲染
- Refactored dispatch logic to control the number of concurrent requests and support priority in request queuing - 重构Dispatch分发逻辑支持控制并发请求数支持请求排队队列的优先级
- Support for custom memory cache strategies and sizes through **initMemoryCache** - 支持通过initMemoryCache自定义策略内存缓存策略和大小
- Support for custom implementation of image acquisition/network downloading through options - 支持option自定义实现图片获取/网络下载
Therefore, there are some differences in APIs and capabilities, which mainly include the following: 因此API及能力上目前有部分差异主要体现在
- The **drawLifeCycle** API is not supported; images are drawn manually through the canvas. - 不支持drawLifeCycle接口通过canvas自会图片
- In the new version, parameters such as **mainScaleType** and **border** are consistent with the system **Image** component. - mainScaleTypeborder等参数新版本与系统Image保持一致
- GIF/WebP animation playback and control (implemented by **ImageAnimator**). - gif/webp动图播放与控制
- Anti-aliasing related parameters. - 抗锯齿相关参数
## How to Install ## 下载安装
``` ```
ohpm install @ohos/imageknife ohpm install @ohos/imageknife
// If file caching is required, initialize the file cache in advance. // 如果需要用文件缓存,需要提前初始化文件缓存
await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024) await ImageKnife.getInstance().initFileCache(context, 256, 256 * 1024 * 1024)
``` ```
## How to Use ## 使用说明
#### 1. Displaying a Local Resource Image #### 1.显示本地资源图片
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 2. Displaying a File from Local Context Files #### 2.显示本地context files下文件
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: this.localFile, loadSrc: this.localFile,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 3. Displaying a Network Image #### 3.显示网络图片
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 4. Downloading an Image with Custom Options #### 4.自定义下载图片
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg", loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Auto, objectFit: ImageFit.Auto,
customGetImage: custom customGetImage: custom
}) }
}).width(100).height(100) }).width(100).height(100)
// Custom implementation of the image acquisition method, such as custom network download。 // 自定义实现图片获取方法,如自定义网络下载
@Concurrent @Concurrent
async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> { async function custom(context: Context, src: string | PixelMap | Resource): Promise<ArrayBuffer | undefined> {
console.info("ImageKnife:: custom download: " + src) console.info("ImageKnife:: custom download" + src)
// Example of hardcoding to read from a local file. You can also request a network image. // 举例写死从本地文件读取,也可以自己请求网络图片
return context.resourceManager.getMediaContentSync($r("app.media.bb").id).buffer as ArrayBuffer return context.resourceManager.getMediaContentSync($r("app.media.bb").id).buffer as ArrayBuffer
} }
``` ```
#### 5. Listening for Network Download Progress #### 5.监听网络下载进度
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
ImageKnifeOption: new ImageKnifeOption({ ImageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)} progressListener:(progress:number)=>{console.info("ImageKinfe:: call back progress = " + progress)}
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 6. Setting Border Options #### 6.支持option传入border设置边框圆角
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
border: {radius:50} border: {radius:50}
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 7. Setting Image Transformation Options #### 7.支持option图片变换
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
border: {radius:50}, border: {radius:50},
transformation: new BlurTransformation(3) transformation: new BlurTransformation(3)
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
Multiple combined transformation usages: 多种组合变换用法
``` ```
let transformations: collections.Array<PixelMapTransformation> = new collections.Array<PixelMapTransformation>(); let transformations: collections.Array<PixelMapTransformation> = new collections.Array<PixelMapTransformation>();
transformations.push(new BlurTransformation(5)); transformations.push(new BlurTransformation(5));
transformations.push(new BrightnessTransformation(0.2)); transformations.push(new BrightnessTransformation(0.2));
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: { topLeft: 50, bottomRight: 50 } }, // Rounded corner settings border: { radius: { topLeft: 50, bottomRight: 50 } }, // 圆角设置
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // Graphic transformation group transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined // 图形变换组
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.rotate ({angle: 90}) // Rotate by 90 degrees. .rotate({ angle: 90 }) // 旋转90度
.contrast(12) // Contrast filter .contrast(12) // 对比度滤波器
``` ```
Other transformation-related properties can be stacked to achieve combined transformation effects. 其他变换相关属性,可叠加实现组合变换效果
Example of circular cropping transformation: 圆形裁剪变换示例
``` ```
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Cover, objectFit: ImageFit.Cover,
border: { radius: 150 } border: { radius: 150 }
}) }
}).width(300) }).width(300)
.height(300) .height(300)
``` ```
Example of Circular cropping with border transformation: 圆形裁剪带边框变换示例
``` ```
ImageKnifeComponent({ ImageKnifeOption:new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
objectFit: ImageFit.Cover, objectFit: ImageFit.Cover,
border: { radius: 150, color: Color.Red, width: 5 } border: { radius: 150, color: Color.Red, width: 5 }
}) }
}).width(300) }).width(300)
.height(300) .height(300)
``` ```
Example of contrast filtering transformation: 对比度滤波变换示例
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample') loadSrc: $r('app.media.pngSample')
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.contrast(12) .contrast(12)
``` ```
Example of rotation transformation: 旋转变换示例
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r('app.media.pngSample') loadSrc: $r('app.media.pngSample')
}) }
}).width(300) }).width(300)
.height(300) .height(300)
.rotate({angle:90}) .rotate({angle:90})
.backgroundColor(Color.Pink) .backgroundColor(Color.Pink)
``` ```
#### 8. Listening for Image Loading Success and Failure #### 8.监听图片加载成功与失败
``` ```
ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption( ImageKnifeComponent({ ImageKnifeOption:
{ {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
onLoadListener:{ onLoadListener:{
@ -241,135 +242,128 @@ ImageKnifeComponent({ ImageKnifeOption: new ImageKnifeOption(
console.info(err) console.info(err)
} }
} }
}) }
}).width(100).height(100) }).width(100).height(100)
``` ```
#### 9. Use of syncLoad #### 9.ImageKnifeComponent - syncLoad
**syncLoad** sets whether to load the image synchronously. By default, the image is loaded asynchronously. When loading a small image, you are advised to set **syncLoad** to **true** so that the image loading can be quickly completed on the main thread. 设置是否同步加载图片默认是异步加载。建议加载尺寸较小的本地图片时将syncLoad设为true因为耗时较短在主线程上执行即可
``` ```
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.pngSample"), loadSrc:$r("app.media.pngSample"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
``` ```
#### 10. Use of ImageKnifeAnimatorComponent #### 10.ImageKnifeAnimatorComponent 示例
``` ```
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption },animatorOption:this.animatorOption
}).width(300).height(300).backgroundColor(Color.Orange).margin({top:30}) }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
``` ```
#### Reuse Scenario ## 接口说明
Clear the component content in the **aboutToRecycle** lifecycle and trigger image loading through watch observeration. ### ImageKnife组件
## Available APIs | 组件名称 | 入参内容 | 功能简介 |
### ImageKnife |-----------------------------|---------------------------------|--------|
| Component | Parameter | Description | | ImageKnifeComponent | ImageKnifeOption | 图片显示组件 |
| --------------------------- | -------------------------------- | ------------ | | ImageKnifeAnimatorComponent | ImageKnifeOption、AnimatorOption | 动图控制组件 |
| ImageKnifeComponent | ImageKnifeOption | Image display component.|
| ImageKnifeAnimatorComponent | ImageKnifeOption, AnimatorOption| Animated image control component.|
### AnimatorOption ### AnimatorOption参数列表
| Parameter | Type | Description | | 参数名称 | 入参内容 | 功能简介 |
| ---------- | --------------- | ---------------------------------------- | |-----------------------|-------------------------------------------------------|----------|
| state | AnimationStatus | Playback status. Optional. | | state | AnimationStatus | 播放状态(可选) |
| iterations | number | Number of playback times. Optional. | | iterations | number | 播放次数(可选) |
| reverse | boolean | Playback order. Optional. | | reverse | boolean | 播放顺序(可选) |
| onStart | ()=>void | Triggered when the animation starts. Optional. |
| onFinish | ()=>void | Triggered when the animation finishes or stops. Optional.|
| onPause | ()=>void | Triggered when the animation pauses. Optional. |
| onCancel | ()=>void | Triggered when the animation is canceled, that is, when it is reset to its initial state. Optional. |
| onRepeat | ()=>void | Triggered when the animation repeats. Optional. |
### ImageKnifeOption ### ImageKnifeOption参数列表
| Parameter | Type | Description | | 参数名称 | 入参内容 | 功能简介 |
| --------------------- | ----------------------------------------------------- | ------------------------------ | |-----------------------|-------------------------------------------------------|-----------------|
| loadSrc | string, PixelMap, Resource | Main image. | | loadSrc | string、PixelMap、Resource | 主图展示 |
| placeholderSrc | PixelMap, Resource | Placeholder image. Optional. | | placeholderSrc | PixelMap、Resource | 占位图图展示(可选) |
| errorholderSrc | PixelMap, Resource | Error image. Optional. | | errorholderSrc | PixelMap、Resource | 错误图展示(可选) |
| objectFit | ImageFit | How the main image is resized to fit its container. Optional. | | objectFit | ImageFit | 主图填充效果(可选) |
| placeholderObjectFit | ImageFit | How the placeholder image is resized to fit its container. Optional. | | placeholderObjectFit | ImageFit | 占位图填充效果(可选) |
| errorholderObjectFit | ImageFit | How the error image is resized to fit its container. Optional. | | errorholderObjectFit | ImageFit | 错误图填充效果(可选) |
| writeCacheStrategy | CacheStrategyType | Cache writing strategy. Optional. | | writeCacheStrategy | CacheStrategyType | 写入缓存策略(可选) |
| onlyRetrieveFromCache | boolean | Whether to skip network and local requests. Optional.| | onlyRetrieveFromCache | boolean | 是否跳过网络和本地请求(可选) |
| customGetImage | (context: Context, src: string | Custom image download. Optional. | | customGetImage | (context: Context, src: string | 自定义下载图片(可选) | | Resource | 错误占位图数据源 |
| border | BorderOptions | Border corner. Optional. | | border | BorderOptions | 边框圆角(可选) |
| priority | taskpool.Priority | Load priority. Optional. | | priority | taskpool.Priority | 加载优先级(可选) |
| context | common.UIAbilityContext | Context. Optional. | | context | common.UIAbilityContext | 上下文(可选) |
| progressListener | (progress: number)=>void | Progress. Optional. | | progressListener | (progress: number)=>void | 进度(可选) |
| signature | String | Custom cache signature. Optional. | | signature | String | 自定义缓存关键字(可选) |
| headerOption | Array\<HeaderOptions> | Request headers. Optional. | | headerOption | Array<HeaderOptions> | 设置请求头(可选) |
| transformation | PixelMapTransformation | Image transformation. Optional. | | transformation | PixelMapTransformation | 图片变换(可选) |
| drawingColorFilter | ColorFilter | Drawing color filter. Optional. | | drawingColorFilter | ColorFilter | drawing.ColorFilter | 图片变换(可选) |
| onComplete | (event:EventImage \| undefined)=>void | Callback for image loading completion. Optional. | | onComplete | (event:EventImage | undefined) => voi | 颜色滤镜效果(可选) |
| onLoadListener | onLoadStart:()=>void,onLoadSuccess:(data:string\|Pixelmap)=>void | Callback for image loading events. Optional. | | onLoadListener | onLoadStart: () => void、onLoadSuccess: (data: string | PixelMap | undefined) => void、onLoadFailed: (err: string) => void| 监听图片加载成功与失败 |
### ImageKnife ### ImageKnife接口
| Parameter | Type | Description | | 参数名称 | 入参内容 | 功能简介 |
| ----------------- | ------------------------------------------------------------ | -------------------------- | |------------------|-------------------------------------------------------------------------------------------------------|---------------|
| initMemoryCache | newMemoryCache: IMemoryCache | Initializes a custom memory cache strategy. | | initMemoryCache | newMemoryCache: IMemoryCache | 自定义内存缓存策略 |
| initFileCache | context: Context, size: number, memory: number | Initializes the file cache size and quantity | | initFileCache | context: Context, size: number, memory: number | 初始化文件缓存数量和大小 |
| preLoadCache | loadSrc: string I ImageKnifeOption | Preloads and returns the file cache path. | | preLoadCache | loadSrc: string I ImageKnifeOption | 预加载并返回文件缓存路径 |
| getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | Obtains resources from memory or file cache.| | getCacheImage | loadSrc: string, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) | 从内存或文件缓存中获取资源 |
| addHeader | key: string, value: Object | Adds a global HTTP request header. | | addHeader | key: string, value: Object | 全局添加http请求头 |
| setHeaderOptions | Array<HeaderOptions> | Sets global HTTP request headers. | | setHeaderOptions | Array<HeaderOptions> | 全局设置http请求头 |
| deleteHeader | key: string | Deletes a global HTTP request header. | | deleteHeader | key: string | 全局删除http请求头 |
| setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | | setCustomGetImage | customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined> | 全局设置自定义下载 |
| setEngineKeyImpl | IEngineKey | Sets a global cache key generation strategy. | | setEngineKeyImpl | IEngineKey | 全局配置缓存key生成策略 |
| putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | Writes to the memory disk cache. | | putCacheImage | url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string | 写入内存磁盘缓存 |
| removeMemoryCache | url: string | Removes an entry from the memory cache. | | removeMemoryCache| url: string | ImageKnifeOption | 清理指定内存缓存 |
| removeFileCache | url: string | Removes an entry from the file cache. | | removeFileCache | url: string | ImageKnifeOption | 清理指定磁盘缓存 |
### Graphics tRansformation Types (GPUImage Dependency Required) ### 图形变换类型需要为GPUImage添加依赖项
| Type | Description | | 类型 | 相关描述 |
| ------------------------ | ----------------------------- | | ---------------------------------- | ----------------------------- |
| BlurTransformation | Blurs the image. | | BlurTransformation | 模糊处理 |
| BrightnessTransformation | Applies a brightness filter. | | BrightnessTransformation | 亮度滤波器 |
| CropSquareTransformation | Crops the image to a square. | | CropSquareTransformation | 正方形剪裁 |
| CropTransformation | Crops the image to a custom rectangle. | | CropTransformation | 自定义矩形剪裁 |
| GrayScaleTransformation | Applies a grayscale filter. | | GrayScaleTransformation | 灰度级滤波器 |
| InvertTransformation | Applies an inversion filter. | | InvertTransformation | 反转滤波器 |
| KuwaharaTransformation | Applies a Kuwahara filter (requires **GPUImage**). | | KuwaharaTransformation | 桑原滤波器使用GPUIImage |
| MaskTransformation | Applies a mask. | | MaskTransformation | 遮罩 |
| PixelationTransformation | Applies a pixelation filter (requires **GPUImage**).| | PixelationTransformation | 像素化滤波器使用GPUIImage |
| SepiaTransformation | Applies a sepia filter (requires **GPUImage**).| | SepiaTransformation | 乌墨色滤波器使用GPUIImage |
| SketchTransformation | Applies a sketch filter (requires **GPUIImage**). | | SketchTransformation | 素描滤波器使用GPUIImage |
| SwirlTransformation | Applies a swirl filter (requires **GPUImage**). | | SwirlTransformation | 扭曲滤波器使用GPUIImage |
| ToonTransformation | Applies a cartoon filter (requires **GPUImage**). | | ToonTransformation | 动画滤波器使用GPUIImage |
| VignetterTransformation | Applies a vignette filter (requires **GPUImage**). | | VignetterTransformation | 装饰滤波器使用GPUIImage |
## Downloading and Installing the GPUImage Dependency ## 下载安装GPUImage依赖
Method 1: In the **Terminal** window, run the following command to install the third-party HAR. DevEco Studio will automatically add the HAR as a dependency to the **oh-package.json5** file of the project. 方法一在Terminal窗口中执行如下命令安装三方包DevEco Studio会自动在工程的oh-package.json5中自动添加三方包依赖。
``` ```
ohpm install @ohos/gpu_transform ohpm install @ohos/gpu_transform
``` ```
Method 2: Set the third-party HAR as a dependency in the **oh-package.json5** file of the project. The following is a configuration example: 方法二: 在工程的oh-package.json5中设置三方包依赖配置示例如下
``` ```
"dependencies": { "dependencies": {
"@ohos/gpu_transform": "^1.0.2" "@ohos/gpu_transform": "^1.0.2"
} }
``` ```
## Constraints ## 约束与限制
This project has been verified in the following version: 在下述版本验证通过:
DevEco Studio 5.0 Canary35.0.3.221--SDK:API12
DevEco Studio: 5.0 Canary3 (5.0.3.502), SDK: API 12 (5.0.0.31) ## 贡献代码
## How to Contribute 使用过程中发现任何问题都可以提 [issue](https://gitee.com/openharmony-tpc/ImageKnife/issues)
给我们,当然,我们也非常欢迎你给我们发 [PR](https://gitee.com/openharmony-tpc/ImageKnife/issues) 。
If you find any problem during the use, submit an [Issue](https://gitee.com/openharmony-tpc/ImageKnife/issues) or a [PR](https://gitee.com/openharmony-tpc/ImageKnife/issues) to us. ## 开源协议
## License 本项目基于 [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE) ,请自由的享受和参与开源。
This project is licensed under [Apache License 2.0](https://gitee.com/openharmony-tpc/ImageKnife/blob/master/LICENSE). ## 遗留问题
## Known Issues - ImageKnifeAnimator组件无法设置ImageFit属性
- ImageKnifeAnimator组件设置border属性无法将图片变为圆角
- The **ImageFit** attribute cannot be set for the **ImageKnifeAnimator** component.
- The **border** attribute of the **ImageKnifeAnimator** component cannot make the image rounded corners.

View File

@ -12,82 +12,44 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { AnimatorOption, ImageKnifeAnimatorComponent,ImageKnifeOption } from "@ohos/libraryimageknife" import { AnimatorOption, ImageKnifeAnimatorComponent } from "@ohos/libraryimageknife"
@Entry @Entry
@ComponentV2 @Component
struct ImageAnimatorPage { struct ImageAnimatorPage {
@Local animatorOption: AnimatorOption = new AnimatorOption({ @State animatorOption: AnimatorOption = {
state: AnimationStatus.Running, state: AnimationStatus.Running,
iterations: -1, iterations: -1
onFinish:()=>{ }
console.log("ImageKnifeAnimatorComponent animatorOption onFinish")
},
onStart:()=>{
console.log("ImageKnifeAnimatorComponent animatorOption onStart")
},
onPause:()=>{
console.log("ImageKnifeAnimatorComponent animatorOption onPause")
},
onCancel:()=>{
console.log("ImageKnifeAnimatorComponent animatorOption onCancel")
},
onRepeat:()=>{
console.log("ImageKnifeAnimatorComponent animatorOption onRepeat")
}
})
@Local animatorOption1: AnimatorOption = new AnimatorOption({
state: AnimationStatus.Initial
})
@Local animatorOption2: AnimatorOption = new AnimatorOption({
state: AnimationStatus.Initial,
reverse: true
})
build() { build() {
Column(){ Column(){
Flex(){ Flex(){
Button($r('app.string.Play')).onClick(()=>{ Button("播放").onClick(()=>{
this.animatorOption.state = AnimationStatus.Running this.animatorOption.state = AnimationStatus.Running
}) })
Button($r('app.string.Pause')).onClick(()=>{ Button("暂停").onClick(()=>{
this.animatorOption.state = AnimationStatus.Paused this.animatorOption.state = AnimationStatus.Paused
}) })
Button($r('app.string.Stop')).onClick(()=>{ Button("停止").onClick(()=>{
this.animatorOption.state = AnimationStatus.Stopped this.animatorOption.state = AnimationStatus.Stopped
}) })
Button($r('app.string.Infinite_loop')).onClick(()=>{ Button("无限循环").onClick(()=>{
this.animatorOption.iterations = -1 this.animatorOption.iterations = -1
}) })
Button($r('app.string.Play_once')).onClick(()=>{ Button("播放一次").onClick(()=>{
this.animatorOption.iterations = 1 this.animatorOption.iterations = 1
}) })
Button($r('app.string.Play_twice')).onClick(()=>{ Button("播放两次").onClick(()=>{
this.animatorOption.iterations = 2 this.animatorOption.iterations = 2
}) })
} }
ImageKnifeAnimatorComponent({ ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption },animatorOption:this.animatorOption
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30}) }).width(300).height(300).backgroundColor(Color.Orange).margin({top:30})
Text($r('app.string.Display_the_first_frame')).fontSize(20)
ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption1
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
Text($r('app.string.Display_the_last_frame')).fontSize(20)
ImageKnifeAnimatorComponent({
imageKnifeOption:new ImageKnifeOption({
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed')
}),animatorOption:this.animatorOption2
}).width(200).height(200).backgroundColor(Color.Orange).margin({top:30})
}.width("100%").height("100%") }.width("100%").height("100%")
} }
} }

View File

@ -35,17 +35,17 @@ import {
import { collections } from '@kit.ArkTS' import { collections } from '@kit.ArkTS'
@Entry @Entry
@ComponentV2 @Component
struct ImageTransformation { struct ImageTransformation {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain objectFit: ImageFit.Contain
}) }
@Local isRound: boolean = false; @State isRound: boolean = false;
@Local isContrast: boolean = false; @State isContrast: boolean = false;
@Local isRotate: boolean = false; @State isRotate: boolean = false;
isBlur: boolean = false isBlur: boolean = false
isBrightness: boolean = false isBrightness: boolean = false
isGrayScale: boolean = false; isGrayScale: boolean = false;
@ -412,14 +412,14 @@ struct ImageTransformation {
if (this.isMask) { if (this.isMask) {
transformations.push(new MaskTransformation($r('app.media.mask_starfish'))); transformations.push(new MaskTransformation($r('app.media.mask_starfish')));
} }
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: $r('app.media.pngSample'), loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: this.isRound ? { topLeft: 50, bottomRight: 50 } : 0 }, border: { radius: this.isRound ? { topLeft: 50, bottomRight: 50 } : 0 },
transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined transformation: transformations.length > 0 ? new MultiTransTransformation(transformations) : undefined
}) }
if (this.isCropCircle) { if (this.isCropCircle) {
this.imageKnifeOption.objectFit = ImageFit.Cover; this.imageKnifeOption.objectFit = ImageFit.Cover;
this.imageKnifeOption.border = { radius: 150 }; this.imageKnifeOption.border = { radius: 150 };

View File

@ -15,7 +15,7 @@
import router from '@system.router'; import router from '@system.router';
@Entry @Entry
@ComponentV2 @Component
struct Index { struct Index {
getResourceString(res:Resource){ getResourceString(res:Resource){

View File

@ -15,11 +15,11 @@
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'; import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct ListPage { struct ListPage {
private data: string[] = [] private data: string[] = []
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ loadSrc: $r('app.media.startIcon')}) @State ImageKnifeOption: ImageKnifeOption = { loadSrc: $r('app.media.startIcon')}
aboutToAppear(): void { aboutToAppear(): void {

View File

@ -16,12 +16,12 @@ import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife"
import matrix4 from '@ohos.matrix4' import matrix4 from '@ohos.matrix4'
@Entry @Entry
@ComponentV2 @Component
struct LoadStatePage { struct LoadStatePage {
starTime:number = new Date().getTime() starTime:number = new Date().getTime()
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State ImageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
@ -35,22 +35,22 @@ struct LoadStatePage {
}, },
}, },
border: { radius: 50 } border: { radius: 50 }
}) }
@Local imageKnifeOption1: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption1: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon') loadSrc: $r('app.media.startIcon')
}) }
@Local message: string = "" @State message: string = ""
@Local currentWidth: number = 200 @State currentWidth: number = 200
@Local currentHeight: number = 200 @State currentHeight: number = 200
@Local typeValue: string = "" @State typeValue: string = ""
build() { build() {
Column() { Column() {
Text($r('app.string.TIPS')) Text('测试失败场景请先关闭网络,并保证本地没有此网络图片的缓存')
.margin({ top: 20 }) .margin({ top: 20 })
Row() { Row() {
Button($r('app.string.Test_failure_success')) Button('测试失败/成功场景')
.onClick(() => { .onClick(() => {
this.ImageKnifeOption = new ImageKnifeOption({ this.ImageKnifeOption = {
loadSrc: "https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc: "https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
@ -75,15 +75,15 @@ struct LoadStatePage {
onComplete:(event)=>{ onComplete:(event)=>{
console.error("Load onComplete width:"+event?.width , " height:"+event?.height , " componentWidth:"+event?.componentWidth," componentHeight:" + event?.componentHeight); console.error("Load onComplete width:"+event?.width , " height:"+event?.height , " componentWidth:"+event?.componentWidth," componentHeight:" + event?.componentHeight);
} }
}) }
}) })
} }
.margin({ top: 20 }) .margin({ top: 20 })
Text(this.typeValue) Text(this.typeValue)
ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth) ImageKnifeComponent({ imageKnifeOption: this.ImageKnifeOption }).height(this.currentHeight).width(this.currentWidth)
.margin({ top: 20 }) .margin({ top: 20 })
Button($r('app.string.Custom_download_failed')).onClick(()=>{ Button("自定义下载失败").onClick(()=>{
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc: "abc", loadSrc: "abc",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
@ -93,7 +93,7 @@ struct LoadStatePage {
this.message = "err:" + err this.message = "err:" + err
} }
} }
}) }
}).margin({ top: 20 }) }).margin({ top: 20 })
Text(this.message).fontSize(20).margin({ top: 20 }) Text(this.message).fontSize(20).margin({ top: 20 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).height(this.currentHeight).width(this.currentWidth) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).height(this.currentHeight).width(this.currentWidth)

View File

@ -12,10 +12,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct LongImagePage { struct LongImagePage {
build() { build() {
@ -25,13 +25,13 @@ struct LongImagePage {
// Image($r("app.media.aaa")).objectFit(ImageFit.Auto).width(200) // Image($r("app.media.aaa")).objectFit(ImageFit.Auto).width(200)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc:"https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg", loadSrc:"https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg",
//src:$r("app.media.aaa"), //src:$r("app.media.aaa"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Auto objectFit: ImageFit.Auto
}) }
}) })
} }
.height('100%') .width('100%') .height('100%') .width('100%')

View File

@ -12,12 +12,12 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { BlurTransformation, ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife'; import { ImageKnifeComponent } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct ManyPhotoShowPage { struct ManyPhotoShowPage {
private data: TestDataSource = new TestDataSource(); private data: TestDataSource = new TestDataSource();
@ -36,16 +36,15 @@ struct ManyPhotoShowPage {
// loadSrc: item.thumbnail, // loadSrc: item.thumbnail,
// mainScaleType: ScaleType.FIT_XY, // mainScaleType: ScaleType.FIT_XY,
// } }) // } })
ImageKnifeComponent({imageKnifeOption:new ImageKnifeOption({ ImageKnifeComponent({imageKnifeOption:{
loadSrc: item.thumbnail, loadSrc: item.thumbnail,
//src:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", //src:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
// src: this.localFile, // src: this.localFile,
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
errorholderSrc:$r("app.media.failed"), errorholderSrc:$r("app.media.failed"),
objectFit: ImageFit.Auto, objectFit: ImageFit.Auto,
border: {radius:50}, border: {radius:50}
transformation:new BlurTransformation(5) }})
})})
} }
.width(56).height(56) .width(56).height(56)
//滤镜标题 //滤镜标题

View File

@ -15,49 +15,49 @@
import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnife, ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct ObjectFitPage { struct ObjectFitPage {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill objectFit: ImageFit.Fill
}) }
build() { build() {
Column() { Column() {
Button($r('app.string.Main_image_Fill')).onClick(()=>{ Button("主图Fill拉伸填充").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: $r("app.media.app_icon"), loadSrc: $r("app.media.app_icon"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill objectFit: ImageFit.Fill
}) }
}) })
Button($r('app.string.Maintain_proportion_filling')).margin({top:10}).onClick(async () => { Button("占位图Contain保持比例填充").margin({top:10}).onClick(async () => {
ImageKnife.getInstance().removeAllMemoryCache() ImageKnife.getInstance().removeAllMemoryCache()
await ImageKnife.getInstance().removeAllFileCache() await ImageKnife.getInstance().removeAllFileCache()
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg", loadSrc: "https://wx2.sinaimg.cn/mw690/006HyQKGgy1hnqp08dw09j30u04twu0x.jpg",
placeholderSrc: $r("app.media.app_icon"), placeholderSrc: $r("app.media.app_icon"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill, objectFit: ImageFit.Fill,
placeholderObjectFit: ImageFit.Contain placeholderObjectFit: ImageFit.Contain
}) }
}) })
Button($r('app.string.Error_graph_None')).margin({top:10}).onClick(() => { Button("错误图None不变化").margin({top:10}).onClick(() => {
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "http://xxxxx", loadSrc: "http://xxxxx",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Fill, objectFit: ImageFit.Fill,
errorholderObjectFit: ImageFit.None errorholderObjectFit: ImageFit.None
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({

View File

@ -16,18 +16,18 @@ import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct SignatureTestPage { struct SignatureTestPage {
@Local imageKnifeOption1: ImageKnifeOption =new ImageKnifeOption( @State imageKnifeOption1: ImageKnifeOption =
{ {
loadSrc: $r('app.media.icon'), loadSrc: $r('app.media.icon'),
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
}); };
@Local imageKnifeOption2: ImageKnifeOption =new ImageKnifeOption( @State imageKnifeOption2: ImageKnifeOption =
{ {
loadSrc: $r('app.media.icon'), loadSrc: $r('app.media.icon'),
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
}); };
build() { build() {
Scroll() { Scroll() {
@ -37,11 +37,11 @@ struct SignatureTestPage {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button($r('app.string.Load')) Button($r('app.string.Load'))
.onClick(() => { .onClick(() => {
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc: 'https://img-blog.csdn.net/20140514114029140', loadSrc: 'https://img-blog.csdn.net/20140514114029140',
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
signature: "1" signature: "1"
}) }
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink) }.width('100%').backgroundColor(Color.Pink)
@ -50,11 +50,11 @@ struct SignatureTestPage {
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) { Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button($r('app.string.Load')) Button($r('app.string.Load'))
.onClick(() => { .onClick(() => {
this.imageKnifeOption2 = new ImageKnifeOption({ this.imageKnifeOption2 = {
loadSrc: 'https://img-blog.csdn.net/20140514114029140', loadSrc: 'https://img-blog.csdn.net/20140514114029140',
placeholderSrc:$r("app.media.loading"), placeholderSrc:$r("app.media.loading"),
signature: new Date().getTime().toString() signature: new Date().getTime().toString()
}) }
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink) }.width('100%').backgroundColor(Color.Pink)

View File

@ -12,19 +12,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,BlurTransformation,ImageKnifeOption } from '@ohos/libraryimageknife'; import { ImageKnifeComponent,BlurTransformation } from '@ohos/libraryimageknife';
import fs from '@ohos.file.fs'; import fs from '@ohos.file.fs';
import image from '@ohos.multimedia.image'; import image from '@ohos.multimedia.image';
import { common2D, drawing } from '@kit.ArkGraphics2D'; import { common2D, drawing } from '@kit.ArkGraphics2D';
@Entry @Entry
@ComponentV2 @Component
struct SingleImage { struct SingleImage {
resource: string = "app.media.svgSample" resource: string = "app.media.svgSample"
scroller: Scroller = new Scroller; scroller: Scroller = new Scroller;
localFile: string = getContext(this).filesDir + "/icon.png" localFile: string = getContext(this).filesDir + "/icon.png"
@Local pixelMap:PixelMap | undefined = undefined; @State pixelMap:PixelMap | undefined = undefined;
@Local DrawingColorFilter: ColorFilter | undefined = undefined @State DrawingColorFilter: ColorFilter | undefined = undefined
private color: common2D.Color = { alpha: 255, red: 255, green: 0, blue: 0 }; private color: common2D.Color = { alpha: 255, red: 255, green: 0, blue: 0 };
aboutToAppear(): void { aboutToAppear(): void {
// 拷贝本地文件 // 拷贝本地文件
@ -46,12 +46,12 @@ struct SingleImage {
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: $r("app.media.svgSample"), loadSrc: $r("app.media.svgSample"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain objectFit: ImageFit.Contain
}) }
}).width(100).height(100) }).width(100).height(100)
.onClick(()=>{ .onClick(()=>{
this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN); this.DrawingColorFilter = drawing.ColorFilter.createBlendModeColorFilter(this.color, drawing.BlendMode.SRC_IN);
@ -60,48 +60,48 @@ struct SingleImage {
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.localFile, loadSrc: this.localFile,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain objectFit: ImageFit.Contain
}) }
}).width(100).height(100) }).width(100).height(100)
Text($r('app.string.Network_images')) Text($r('app.string.Network_images'))
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png", loadSrc:"https://www.openharmony.cn/_nuxt/img/logo.dcf95b3.png",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)} progressListener:(progress:number)=>{console.info("ImageKnife:: call back progress = " + progress)}
}) }
}).width(100).height(100) }).width(100).height(100)
Text($r('app.string.Custom_network_download')) Text($r('app.string.Custom_network_download'))
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg", loadSrc: "https://file.atomgit.com/uploads/user/1704857786989_8994.jpeg",
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
customGetImage: custom, customGetImage: custom,
transformation: new BlurTransformation(10) transformation: new BlurTransformation(10)
}) }
}).width(100).height(100) }).width(100).height(100)
Text($r('app.string.PixelMap_loads_images')) Text($r('app.string.PixelMap_loads_images'))
.fontSize(30) .fontSize(30)
.fontWeight(FontWeight.Bold) .fontWeight(FontWeight.Bold)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.pixelMap!, loadSrc: this.pixelMap!,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
}) }
}).width(100).height(100) }).width(100).height(100)
} }
.width('100%') .width('100%')

View File

@ -12,10 +12,10 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent ,ImageKnifeOption} from '@ohos/libraryimageknife'; import { ImageKnifeComponent } from '@ohos/libraryimageknife';
@Entry @Entry
@ComponentV2 @Component
struct TestCommonImage { struct TestCommonImage {
private data: Array<string> = [] private data: Array<string> = []
aboutToAppear(): void { aboutToAppear(): void {
@ -30,13 +30,13 @@ struct TestCommonImage {
FlowItem() { FlowItem() {
Column(){ Column(){
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: item, loadSrc: item,
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.failed"), errorholderSrc: $r("app.media.failed"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
signature: "aaa" signature: "aaa"
}) }
}).width("50%").height(200) }).width("50%").height(200)
} }
}.height(200) }.height(200)

View File

@ -12,34 +12,34 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestErrorHolderPage { struct TestErrorHolderPage {
build() { build() {
Column() { Column() {
Text("ImageKnifeComponent1").fontSize(20) Text("ImageKnifeComponent1").fontSize(20)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "abc", loadSrc: "abc",
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
}).width(200).height(200) }).width(200).height(200)
Text("ImageKnifeComponent2").fontSize(20) Text("ImageKnifeComponent2").fontSize(20)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "abc", loadSrc: "abc",
errorholderSrc:$r('app.media.startIcon') errorholderSrc:$r('app.media.startIcon')
}) }
}).width(200).height(200) }).width(200).height(200)
Text("ImageKnifeComponent2").fontSize(20) Text("ImageKnifeComponent2").fontSize(20)
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: "abc", loadSrc: "abc",
errorholderSrc:$r('app.media.mask_starfish') errorholderSrc:$r('app.media.mask_starfish')
}) }
}).width(200).height(200) }).width(200).height(200)
} }
.height('100%') .width('100%') .height('100%') .width('100%')

View File

@ -15,9 +15,9 @@
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestPrefetchToFileCachePage { struct TestPrefetchToFileCachePage {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658", loadSrc:"https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
headerOption:[ headerOption:[
@ -26,7 +26,7 @@ struct TestPrefetchToFileCachePage {
value:"单个" value:"单个"
} }
] ]
}) }
build() { build() {
Column() { Column() {

View File

@ -15,7 +15,7 @@
import { IndexComponent } from "@ohos/libraryimageknife" import { IndexComponent } from "@ohos/libraryimageknife"
@Entry @Entry
@ComponentV2 @Component
struct TestHspPreLoadImage { struct TestHspPreLoadImage {
build() { build() {
Column() { Column() {

View File

@ -12,9 +12,9 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent } from '@ohos/libraryimageknife'
@ObservedV2 @Observed
export class MsgModel { export class MsgModel {
id: string id: string
cId: string cId: string
@ -30,10 +30,10 @@ export class MsgModel {
} }
// @Reusable @Reusable
@ComponentV2 @Component
export struct MsgItem { export struct MsgItem {
@Param count: number = 0 count: number = 0
private data: Array<string> = [ private data: Array<string> = [
"http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg", "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg",
"http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg", "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg",
@ -59,37 +59,37 @@ export struct MsgItem {
build(){ build(){
if (this.count % 2 == 0 && this.count <6){ if (this.count % 2 == 0 && this.count <6){
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.startIcon"), loadSrc:$r("app.media.startIcon"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
}else if (this.count > 6 && this.count - 6 < this.data.length){ }else if (this.count > 6 && this.count - 6 < this.data.length){
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:this.data[this.count - 6], loadSrc:this.data[this.count - 6],
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
}else { }else {
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption:new ImageKnifeOption({ imageKnifeOption:{
loadSrc:$r("app.media.pngSample"), loadSrc:$r("app.media.pngSample"),
placeholderSrc:$r("app.media.loading") placeholderSrc:$r("app.media.loading")
}),syncLoad:true },syncLoad:true
}) })
} }
} }
} }
@Entry @Entry
@ComponentV2 @Component
struct ImageTestPage { struct ImageTestPage {
count : number = 0 count : number = 0
rCount: number = 0 rCount: number = 0
scroller: Scroller = new Scroller() scroller: Scroller = new Scroller()
@Local list: MsgModel[] = [] @State list: MsgModel[] = []
@Local imageSize: number =100 @State imageSize: number =100
handAdd(){ handAdd(){
this.count++ this.count++
const msgItem = new MsgModel('add_id'+this.count, 'addBody'+this.count,'cId'+ this.count) const msgItem = new MsgModel('add_id'+this.count, 'addBody'+this.count,'cId'+ this.count)

View File

@ -15,15 +15,15 @@
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestIsUrlExist { struct TestIsUrlExist {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon'), loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading'), placeholderSrc: $r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local source: PixelMap | string | Resource = $r("app.media.startIcon") @State source: PixelMap | string | Resource = $r("app.media.startIcon")
@Local source1: PixelMap | string | Resource = $r("app.media.startIcon") @State source1: PixelMap | string | Resource = $r("app.media.startIcon")
build() { build() {
Column() { Column() {

View File

@ -15,19 +15,19 @@
import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent,ImageKnife,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestPrefetchToFileCachePage { struct TestPrefetchToFileCachePage {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
async preload(url:string) { async preload(url:string) {
let fileCachePath = await ImageKnife.getInstance().preLoadCache(url) let fileCachePath = await ImageKnife.getInstance().preLoadCache(url)
console.log("preload-fileCachePath=="+ fileCachePath) console.log("preload-fileCachePath=="+ fileCachePath)
} }
async preload1(url:string) { async preload1(url:string) {
let fileCachePath = await ImageKnife.getInstance().preLoadCache(new ImageKnifeOption({ loadSrc: url })) let fileCachePath = await ImageKnife.getInstance().preLoadCache({ loadSrc: url })
console.log("preload-fileCachePath1=="+ fileCachePath) console.log("preload-fileCachePath1=="+ fileCachePath)
} }
build() { build() {

View File

@ -15,16 +15,16 @@
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnife, ImageKnifeOption, CacheStrategy } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestRemoveCache { struct TestRemoveCache {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon'), loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading'), placeholderSrc: $r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local source: PixelMap | string | Resource = $r("app.media.startIcon"); @State source: PixelMap | string | Resource = $r("app.media.startIcon");
@Local source1: PixelMap | string | Resource = $r("app.media.startIcon"); @State source1: PixelMap | string | Resource = $r("app.media.startIcon");
@Local url: string = ''; @State url: string = '';
build() { build() {
Column() { Column() {

View File

@ -15,17 +15,12 @@
import { ImageKnifeComponent, ImageKnife, ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnife, ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestSetCustomImagePage { struct TestSetCustomImagePage {
@State imageKnifeOption: ImageKnifeOption = {
getResourceString(res:Resource){
return getContext().resourceManager.getStringSync(res.id)
}
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({
loadSrc: $r('app.media.startIcon'), loadSrc: $r('app.media.startIcon'),
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
aboutToAppear(): void { aboutToAppear(): void {
ImageKnife.getInstance().setCustomGetImage(custom) ImageKnife.getInstance().setCustomGetImage(custom)
} }
@ -34,23 +29,23 @@ struct TestSetCustomImagePage {
} }
build() { build() {
Column() { Column() {
Button(this.getResourceString($r('app.string.Custom_network_download')) + " a").onClick(()=>{ Button("自定义下载a").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "aaa", loadSrc: "aaa",
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
}) })
Button(this.getResourceString($r('app.string.Custom_network_download')) + " b").onClick(()=>{ Button("自定义下载b").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "bbb", loadSrc: "bbb",
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
}) })
Button(this.getResourceString($r('app.string.Custom_network_download')) + " c").onClick(()=>{ Button("自定义下载c").onClick(()=>{
this.imageKnifeOption = new ImageKnifeOption({ this.imageKnifeOption = {
loadSrc: "ccc", loadSrc: "ccc",
placeholderSrc: $r('app.media.loading') placeholderSrc: $r('app.media.loading')
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption imageKnifeOption: this.imageKnifeOption

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { ImageKnifeComponent, ImageKnifeOption } from "@ohos/libraryimageknife" import { ImageKnifeComponent } from "@ohos/libraryimageknife"
@ComponentV2 @ComponentV2
export struct ZuImage { export struct ZuImage {
@ -24,12 +24,12 @@ export struct ZuImage {
if (this.src) { if (this.src) {
//当前版本存在bug //当前版本存在bug
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: new ImageKnifeOption({ imageKnifeOption: {
loadSrc: this.src, loadSrc: this.src,
placeholderSrc: this.placeholderSrc, placeholderSrc: this.placeholderSrc,
errorholderSrc: this.errorholderSrc ?? this.placeholderSrc, errorholderSrc: this.errorholderSrc ?? this.placeholderSrc,
objectFit: ImageFit.Cover objectFit: ImageFit.Cover
}) }
}) })
} else { } else {
Image(this.placeholderSrc) Image(this.placeholderSrc)

View File

@ -15,55 +15,55 @@
import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent,CacheStrategy,ImageKnifeOption } from '@ohos/libraryimageknife'
@Entry @Entry
@ComponentV2 @Component
struct TestWriteCacheStage { struct TestWriteCacheStage {
@Local imageKnifeOption1: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption1: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local imageKnifeOption2: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption2: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
@Local imageKnifeOption3: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption3: ImageKnifeOption = {
loadSrc:$r('app.media.startIcon'), loadSrc:$r('app.media.startIcon'),
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed') errorholderSrc:$r('app.media.failed')
}) }
build() { build() {
Column() { Column() {
Button($r('app.string.Write_memory_and_file')).margin({top:10}).onClick(async ()=>{ Button("写入内存文件缓存").margin({top:10}).onClick(async ()=>{
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc:'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', loadSrc:'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
writeCacheStrategy:CacheStrategy.Default writeCacheStrategy:CacheStrategy.Default
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption1 imageKnifeOption: this.imageKnifeOption1
}).width(200).height(200).margin({top:10}) }).width(200).height(200).margin({top:10})
Button($r('app.string.Write_memory')).margin({top:10}).onClick(async ()=>{ Button("写入内存缓存").margin({top:10}).onClick(async ()=>{
this.imageKnifeOption2 = new ImageKnifeOption({ this.imageKnifeOption2 = {
loadSrc:"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB", loadSrc:"https://hbimg.huabanimg.com/cc6af25f8d782d3cf3122bef4e61571378271145735e9-vEVggB",
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
writeCacheStrategy:CacheStrategy.Memory writeCacheStrategy:CacheStrategy.Memory
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption2 imageKnifeOption: this.imageKnifeOption2
}).width(200).height(200).margin({top:10}) }).width(200).height(200).margin({top:10})
Button($r('app.string.Write_file')).margin({top:10}).onClick(async ()=>{ Button("写入文件缓存").margin({top:10}).onClick(async ()=>{
this.imageKnifeOption3 = new ImageKnifeOption({ this.imageKnifeOption3 = {
loadSrc:'https://img-blog.csdn.net/20140514114029140', loadSrc:'https://img-blog.csdn.net/20140514114029140',
placeholderSrc:$r('app.media.loading'), placeholderSrc:$r('app.media.loading'),
errorholderSrc:$r('app.media.failed'), errorholderSrc:$r('app.media.failed'),
writeCacheStrategy:CacheStrategy.File writeCacheStrategy:CacheStrategy.File
}) }
}) })
ImageKnifeComponent({ ImageKnifeComponent({
imageKnifeOption: this.imageKnifeOption3 imageKnifeOption: this.imageKnifeOption3

View File

@ -17,17 +17,17 @@ import matrix4 from '@ohos.matrix4'
@Entry @Entry
@ComponentV2 @Component
struct TransformPage { struct TransformPage {
private custom_scale:number = 1 private custom_scale:number = 1
@Local matrix1:object = matrix4.identity().scale({ x: 1, y: 1 }) @State matrix1:object = matrix4.identity().scale({ x: 1, y: 1 })
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State ImageKnifeOption: ImageKnifeOption = {
loadSrc: $r("app.media.rabbit"), loadSrc: $r("app.media.rabbit"),
placeholderSrc: $r("app.media.loading"), placeholderSrc: $r("app.media.loading"),
errorholderSrc: $r("app.media.app_icon"), errorholderSrc: $r("app.media.app_icon"),
objectFit: ImageFit.Contain, objectFit: ImageFit.Contain,
border: { radius: 50 } border: { radius: 50 }
}) }
build() { build() {
Column() { Column() {

View File

@ -15,50 +15,24 @@
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife' import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/libraryimageknife'
// const logger = new imUtils.logger.IMLogger('Avatar') // const logger = new imUtils.logger.IMLogger('Avatar')
@ObservedV2
export class MyStorage { class MyImageOption extends ImageKnifeOption {
static instance:MyStorage | undefined = undefined account?: string
static getInstance(){
if(MyStorage.instance == undefined) {
MyStorage.instance = new MyStorage()
}
return MyStorage.instance
}
@Trace WeLink_Mob_fontSize_multiple: number = 1
} }
@ComponentV2 @Component
export struct UserAvatar { export struct UserAvatar {
@Prop @Watch('userInfoUpdate') userInfo: string = ""
// @Prop userInfo: string = "" // @Prop userInfo: string = ""
imgSize: number = 100 imgSize: number = 100
radius: number = 12 radius: number = 12
borderSize: number = 0 borderSize: number = 0
imgSizes: number = 1 imgSizes: number = 1
@Local ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption() @State ImageKnifeOption: ImageKnifeOption = new ImageKnifeOption()
@StorageProp('WeLink_Mob_fontSize_multiple') @Watch('updateImgSize') WeLink_Mob_fontSize_multiple: number = 0
scalable: boolean = true; scalable: boolean = true;
@Local calcImgSize: number = 100 @State calcImgSize: number = 100
@Param userInfo: string = ""
@Monitor('userInfo')
userInfoUpdate() {
// if (uri === 'userInfo' && this.imageKnifeOption.account !== this.userInfo.contactId) return;
// // logger.info(`userInfoUpdate uri=${uri} oldAcc=${this.imageKnifeOption.loadSrc} nowAcc=${this.userInfo.externalHeadUrl}`)
// if (this.userInfo.externalHeadUrl === this.imageKnifeOption.loadSrc && this.userInfo.infoUpdateTime.getTime()
// .toString() === this.imageKnifeOption?.signature?.getKey()) return;
this.ImageKnifeOption = new ImageKnifeOption({
//TODO:写死loadSRC场景变更组件大小所有图片不显示
loadSrc: this.userInfo,
placeholderSrc: $r('app.media.loading'),
errorholderSrc: $r('app.media.failed'),
border: { radius:20,width:5,color:$r('app.color.start_window_background') },
objectFit:ImageFit.Contain
// signature: new ObjectKey(this.userInfo.infoUpdateTime.getTime().toString())
})
}
@Local storage: MyStorage = MyStorage.getInstance()
@Monitor('storage.WeLink_Mob_fontSize_multiple')
updateImgSize() {
this.setImageSize()
}
aboutToAppear(): void { aboutToAppear(): void {
this.userInfoUpdate() this.userInfoUpdate()
this.setImageSize() this.setImageSize()
@ -67,19 +41,39 @@ export struct UserAvatar {
setImageSize() { setImageSize() {
if (!this.scalable) { if (!this.scalable) {
this.calcImgSize = this.imgSize this.calcImgSize = this.imgSize
} else if (this.storage.WeLink_Mob_fontSize_multiple < 0.9) { } else if (this.WeLink_Mob_fontSize_multiple < 0.9) {
this.calcImgSize = this.imgSize * 0.9 this.calcImgSize = this.imgSize * 0.9
} else if (this.storage.WeLink_Mob_fontSize_multiple > 1.6) { } else if (this.WeLink_Mob_fontSize_multiple > 1.6) {
this.calcImgSize = this.imgSize * 1.6 this.calcImgSize = this.imgSize * 1.6
} else { } else {
this.calcImgSize = this.imgSize * this.storage.WeLink_Mob_fontSize_multiple this.calcImgSize = this.imgSize * this.WeLink_Mob_fontSize_multiple
} }
} }
updateImgSize() {
this.setImageSize()
}
aboutToReuse(param: ESObject) { aboutToReuse(param: ESObject) {
this.userInfoUpdate() this.userInfoUpdate()
} }
userInfoUpdate() {
// if (uri === 'userInfo' && this.imageKnifeOption.account !== this.userInfo.contactId) return;
// // logger.info(`userInfoUpdate uri=${uri} oldAcc=${this.imageKnifeOption.loadSrc} nowAcc=${this.userInfo.externalHeadUrl}`)
// if (this.userInfo.externalHeadUrl === this.imageKnifeOption.loadSrc && this.userInfo.infoUpdateTime.getTime()
// .toString() === this.imageKnifeOption?.signature?.getKey()) return;
this.ImageKnifeOption = {
//TODO:写死loadSRC场景变更组件大小所有图片不显示
loadSrc: this.userInfo,
placeholderSrc: $r('app.media.loading'),
errorholderSrc: $r('app.media.failed'),
border: { radius:20,width:5,color:$r('app.color.start_window_background') },
objectFit:ImageFit.Contain
// signature: new ObjectKey(this.userInfo.infoUpdateTime.getTime().toString())
}
}
build() { build() {
Row() { Row() {
// Image(this.imageKnifeOption.loadSrc) // Image(this.imageKnifeOption.loadSrc)

View File

@ -12,7 +12,7 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import { MyStorage, UserAvatar } from './User' import { UserAvatar } from './User'
class CommonDataSource <T> implements IDataSource { class CommonDataSource <T> implements IDataSource {
private dataArray: T[] = [] private dataArray: T[] = []
@ -55,9 +55,9 @@ class CommonDataSource <T> implements IDataSource {
} }
} }
@Entry @Entry
@ComponentV2 @Component
struct Index { struct Index {
@Local hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([]) @State hotCommendList:CommonDataSource<string> = new CommonDataSource<string>([])
private data:string[] = [ private data:string[] = [
"http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg", "http://e.hiphotos.baidu.com/image/pic/item/a1ec08fa513d2697e542494057fbb2fb4316d81e.jpg",
"http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg", "http://c.hiphotos.baidu.com/image/pic/item/30adcbef76094b36de8a2fe5a1cc7cd98d109d99.jpg",
@ -85,42 +85,26 @@ struct Index {
'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp', 'https://hbimg.huabanimg.com/95a6d37a39aa0b70d48fa18dc7df8309e2e0e8e85571e-x4hhks_fw658/format/webp',
] ]
aboutToAppear(): void { aboutToAppear(): void {
MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 1 this.hotCommendList.addData(this.hotCommendList.totalCount(),this.data)
AppStorage.set("WeLink_Mob_fontSize_multiple",1)
} }
build() { build() {
Column() { Column() {
Button("bigger").onClick(()=>{ Button("bigger").onClick(()=>{
MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 1.6 AppStorage.set("WeLink_Mob_fontSize_multiple",1.6)
}) })
Button("small").onClick(()=>{ Button("small").onClick(()=>{
MyStorage.getInstance().WeLink_Mob_fontSize_multiple = 0.8 AppStorage.set("WeLink_Mob_fontSize_multiple",0.8)
}) })
List(){ List(){
// LazyForEach(this.hotCommendList,(item:string)=>{ LazyForEach(this.hotCommendList,(item:string)=>{
// ListItem(){ ListItem(){
// ReuseImage({ ReuseImage({
// userInfo:item userInfo:item
// }).width("100%").height("100%").backgroundColor(Color.Yellow) }).width("100%").height("100%").backgroundColor(Color.Yellow)
// }.width(200).height(200).margin({bottom:5}) }.width(200).height(200).margin({bottom:5})
// }) })
Repeat(this.data)
.each((repeatItem)=>{
ListItem(){
ReuseImage({
userInfo:repeatItem.item
}).width("100%").height("100%").backgroundColor(Color.Yellow)
}.width(200).height(200).margin({bottom:5}).key("reuse")
})
.key(item => item+"reuse")
.virtualScroll()
.template("1",(repeatItem)=>{
ListItem(){
ReuseImage({
userInfo:repeatItem.item
}).width("100%").height("100%").backgroundColor(Color.Yellow)
}.width(200).height(200).margin({bottom:5}).key("reuse")
})
} }
// .cachedCount(20) // .cachedCount(20)
.width("100%") .width("100%")
@ -131,13 +115,13 @@ struct Index {
} }
// @Reusable @Reusable
@ComponentV2 @Component
struct ReuseImage { struct ReuseImage {
@Param userInfo:string = "" @State userInfo:string = ""
// aboutToReuse(params: ESObject): void { aboutToReuse(params: ESObject): void {
// this.userInfo = params.userInfo this.userInfo = params.userInfo
// } }
build() { build() {
Column(){ Column(){

View File

@ -18,15 +18,15 @@ import { photoAccessHelper } from '@kit.MediaLibraryKit';
@Entry @Entry
@ComponentV2 @Component
struct DataShareUriLoadPage { struct DataShareUriLoadPage {
@Local imageKnifeOption1: ImageKnifeOption = @State imageKnifeOption1: ImageKnifeOption =
new ImageKnifeOption({ {
loadSrc: $r('app.media.icon'), loadSrc: $r('app.media.icon'),
placeholderSrc: $r('app.media.loading'), placeholderSrc: $r('app.media.loading'),
errorholderSrc: $r('app.media.failed') errorholderSrc: $r('app.media.failed')
}); };
build() { build() {
@ -43,10 +43,10 @@ struct DataShareUriLoadPage {
let photoViewPicker = new photoAccessHelper.PhotoViewPicker(); let photoViewPicker = new photoAccessHelper.PhotoViewPicker();
let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions); let photoSelectResult: photoAccessHelper.PhotoSelectResult = await photoViewPicker.select(photoSelectOptions);
uris = photoSelectResult.photoUris; uris = photoSelectResult.photoUris;
this.imageKnifeOption1 = new ImageKnifeOption({ this.imageKnifeOption1 = {
loadSrc: uris[0], loadSrc: uris[0],
placeholderSrc:$r('app.media.loading') placeholderSrc:$r('app.media.loading')
}) }
}).margin({ top: 5, left: 3 }) }).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300) ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink) }.width('100%').backgroundColor(Color.Pink)

View File

@ -191,10 +191,10 @@ export class ImageKnife {
*/ */
getCacheImage(loadSrc: string, getCacheImage(loadSrc: string,
cacheType: CacheStrategy = CacheStrategy.Default, signature?: string): Promise<ImageKnifeData | undefined> { cacheType: CacheStrategy = CacheStrategy.Default, signature?: string): Promise<ImageKnifeData | undefined> {
let option: ImageKnifeOption = new ImageKnifeOption({ let option: ImageKnifeOption = {
loadSrc: loadSrc, loadSrc: loadSrc,
signature:signature signature:signature
}) }
let engineKeyImpl: IEngineKey = this.getEngineKeyImpl(); let engineKeyImpl: IEngineKey = this.getEngineKeyImpl();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
@ -218,7 +218,7 @@ export class ImageKnife {
*/ */
putCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) { putCacheImage(url: string, pixelMap: PixelMap, cacheType: CacheStrategy = CacheStrategy.Default, signature?: string) {
let memoryKey = this.getEngineKeyImpl() let memoryKey = this.getEngineKeyImpl()
.generateMemoryKey(url, ImageKnifeRequestSource.SRC, new ImageKnifeOption({ loadSrc: url, signature: signature })); .generateMemoryKey(url, ImageKnifeRequestSource.SRC, { loadSrc: url, signature: signature });
let fileKey = this.getEngineKeyImpl().generateFileKey(url, signature); let fileKey = this.getEngineKeyImpl().generateFileKey(url, signature);
let imageKnifeData: ImageKnifeData = { source: pixelMap, imageWidth: 0, imageHeight: 0 }; let imageKnifeData: ImageKnifeData = { source: pixelMap, imageWidth: 0, imageHeight: 0 };
switch (cacheType) { switch (cacheType) {
@ -252,9 +252,9 @@ export class ImageKnife {
if (url instanceof ImageKnifeOption) { if (url instanceof ImageKnifeOption) {
imageKnifeOption = url; imageKnifeOption = url;
} else { } else {
imageKnifeOption = new ImageKnifeOption({ imageKnifeOption = {
loadSrc: url loadSrc: url
}); };
} }
let key = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature); let key = this.getEngineKeyImpl().generateFileKey(imageKnifeOption.loadSrc, imageKnifeOption.signature);
if (this.fileCache !== undefined) { if (this.fileCache !== undefined) {

View File

@ -19,14 +19,15 @@ import { ImageKnife } from '../ImageKnife';
import { LogUtil } from '../utils/LogUtil'; import { LogUtil } from '../utils/LogUtil';
import { ImageKnifeRequestSource } from '../model/ImageKnifeData'; import { ImageKnifeRequestSource } from '../model/ImageKnifeData';
@ComponentV2 @Component
export struct ImageKnifeAnimatorComponent { export struct ImageKnifeAnimatorComponent {
@Param animatorOption: AnimatorOption = new AnimatorOption(); @Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
@Local pixelMap: PixelMap | string | undefined = undefined @State animatorOption: AnimatorOption = new AnimatorOption();
@Local imageAnimator: Array<ImageFrameInfo> | undefined = undefined @State pixelMap: PixelMap | string | undefined = undefined
@Local adaptiveWidth: Length = '100%' @State imageAnimator: Array<ImageFrameInfo> | undefined = undefined
@Local adaptiveHeight: Length = '100%' @State adaptiveWidth: Length = '100%'
@Local objectFit: ImageFit = ImageFit.Contain @State adaptiveHeight: Length = '100%'
@State objectFit: ImageFit = ImageFit.Contain
private request: ImageKnifeRequest | undefined private request: ImageKnifeRequest | undefined
private lastWidth: number = 0 private lastWidth: number = 0
private lastHeight: number = 0 private lastHeight: number = 0
@ -34,17 +35,7 @@ export struct ImageKnifeAnimatorComponent {
private currentHeight: number = 0 private currentHeight: number = 0
private componentVersion: number = 0 private componentVersion: number = 0
private currentContext: common.UIAbilityContext | undefined = undefined private currentContext: common.UIAbilityContext | undefined = undefined
@Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption();
@Monitor('imageKnifeOption',
"imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit")
watchImageKnifeOption() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
}
this.request = undefined
this.componentVersion++
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
aboutToAppear(): void { aboutToAppear(): void {
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} }
@ -95,6 +86,15 @@ export struct ImageKnifeAnimatorComponent {
.onRepeat(this.animatorOption.onRepeat) .onRepeat(this.animatorOption.onRepeat)
} }
watchImageKnifeOption() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
}
this.request = undefined
this.componentVersion++
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight),true)
}
getCurrentContext(): common.UIAbilityContext { getCurrentContext(): common.UIAbilityContext {
if (this.currentContext == undefined) { if (this.currentContext == undefined) {
this.currentContext = getContext(this) as common.UIAbilityContext this.currentContext = getContext(this) as common.UIAbilityContext

View File

@ -21,13 +21,14 @@ import { ImageKnifeData, ImageKnifeRequestSource } from '../model/ImageKnifeData
import { IEngineKey } from '../key/IEngineKey'; import { IEngineKey } from '../key/IEngineKey';
import { DefaultEngineKey } from '../key/DefaultEngineKey'; import { DefaultEngineKey } from '../key/DefaultEngineKey';
@ComponentV2 @Component
export struct ImageKnifeComponent { export struct ImageKnifeComponent {
@Local pixelMap: PixelMap | string | undefined = undefined @Watch('watchImageKnifeOption') @ObjectLink imageKnifeOption: ImageKnifeOption;
@Param syncLoad: boolean = false @State pixelMap: PixelMap | string | undefined = undefined
@Local adaptiveWidth: Length = '100%' @State syncLoad: boolean = false
@Local adaptiveHeight: Length = '100%' @State adaptiveWidth: Length = '100%'
@Local objectFit: ImageFit = ImageFit.Contain @State adaptiveHeight: Length = '100%'
@State objectFit: ImageFit = ImageFit.Contain
private request: ImageKnifeRequest | undefined private request: ImageKnifeRequest | undefined
private lastWidth: number = 0 private lastWidth: number = 0
private lastHeight: number = 0 private lastHeight: number = 0
@ -35,65 +36,45 @@ export struct ImageKnifeComponent {
private currentHeight: number = 0 private currentHeight: number = 0
private componentVersion: number = 0 private componentVersion: number = 0
private currentContext: common.UIAbilityContext | undefined = undefined private currentContext: common.UIAbilityContext | undefined = undefined
@Param imageKnifeOption: ImageKnifeOption = new ImageKnifeOption();
@Monitor('imageKnifeOption',
"imageKnifeOption.loadSrc","imageKnifeOption.signature","imageKnifeOption.transformation","imageKnifeOption.border","imageKnifeOption.objectFit")
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 { aboutToAppear(): void {
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit //闪动问题失效,注释相应代码后续修复
if(this.syncLoad) {
if(this.syncLoad) { //针对部分消息列表最新消息的图片闪动问题建议使用同步方式在aboutToAppear时加载图片
let engineKey: IEngineKey = new DefaultEngineKey(); let engineKey: IEngineKey = new DefaultEngineKey();
let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance() let memoryCacheSrc: ImageKnifeData | undefined = ImageKnife.getInstance()
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption)) .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
if (memoryCacheSrc !== undefined){ if (memoryCacheSrc !== undefined){
LogUtil.log("aboutToAppear success load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc) LogUtil.log("aboutToAppear load from memory cache for key = "+ engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
//画主图
this.pixelMap = memoryCacheSrc.source; this.pixelMap = memoryCacheSrc.source;
}else{ }else {
LogUtil.log("aboutToAppear fail load loadSrc from memory cache for loadSrc = "+ this.imageKnifeOption.loadSrc) let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance()
if (this.imageKnifeOption.placeholderSrc !== undefined){ .loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption))
let memoryCachePlace: ImageKnifeData | undefined = ImageKnife.getInstance() if (memoryCachePlace !== undefined){
.loadFromMemoryCache(engineKey.generateMemoryKey(this.imageKnifeOption.placeholderSrc!,ImageKnifeRequestSource.PLACE_HOLDER,this.imageKnifeOption)) LogUtil.log("aboutToAppear load from memory cache for key = "+ engineKey.generateMemoryKey(this.imageKnifeOption.loadSrc,ImageKnifeRequestSource.SRC,this.imageKnifeOption))
if (memoryCachePlace !== undefined){ //画主图
LogUtil.log("aboutToAppear success load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc) this.pixelMap = memoryCachePlace.source;
this.pixelMap = memoryCachePlace.source;
}else{
LogUtil.log("aboutToAppear fail load placeholderSrc from memory cache for placeholderSrc = " + this.imageKnifeOption.placeholderSrc)
}
} }
} }
} }
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
} }
aboutToDisappear(): void { aboutToDisappear(): void {
this.clearLastRequest()
}
aboutToRecycle() {
this.clearLastRequest()
}
/**
* 对已DESTROY的组件不再发起请求
*/
private clearLastRequest(){
if (this.request !== undefined) { if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY this.request.requestState = ImageKnifeRequestState.DESTROY
this.request = undefined this.request = undefined
} }
} }
aboutToRecycle() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
this.request = undefined
}
this.objectFit = this.imageKnifeOption.objectFit === undefined ? ImageFit.Contain : this.imageKnifeOption.objectFit
}
build() { build() {
Image(this.pixelMap) Image(this.pixelMap)
.colorFilter(this.imageKnifeOption.drawingColorFilter) .colorFilter(this.imageKnifeOption.drawingColorFilter)
@ -109,19 +90,27 @@ export struct ImageKnifeComponent {
this.currentHeight = newValue.height as number this.currentHeight = newValue.height as number
this.lastWidth = oldValue.width as number this.lastWidth = oldValue.width as number
this.lastHeight = oldValue.height as number this.lastHeight = oldValue.height as number
if (this.currentWidth <= 0 || this.currentHeight <= 0) {
// 条件1: 宽高值均有效,值>0. 条件2当前宽高与上一次宽高不同 // 存在宽或者高为0,此次重回无意义,无需进行request请求
if (this.currentWidth > 0 && this.currentHeight > 0 && } else {
(this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth)) { // 前提:宽高值均有效,值>0. 条件1当前宽高与上一次宽高不同 条件2:当前是第一次绘制
LogUtil.log("onSizeChange execute request:width=" + this.currentWidth + " height= " + this.currentHeight if (this.currentHeight != this.lastHeight || this.currentWidth != this.lastWidth) {
+ " loadSrc = " + this.request?.imageKnifeOption.loadSrc LogUtil.log("execute request:width=" + this.currentWidth + " height= " + this.currentHeight)
+ " placeholderSrc = " + this.request?.imageKnifeOption.placeholderSrc ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
+ " errorholderSrc = " + this.request?.imageKnifeOption.errorholderSrc) }
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
} }
}) })
} }
watchImageKnifeOption() {
if (this.request !== undefined) {
this.request.requestState = ImageKnifeRequestState.DESTROY
}
this.request = undefined
this.componentVersion++
ImageKnife.getInstance().execute(this.getRequest(this.currentWidth, this.currentHeight))
}
getCurrentContext(): common.UIAbilityContext { getCurrentContext(): common.UIAbilityContext {
if (this.currentContext == undefined) { if (this.currentContext == undefined) {
this.currentContext = getContext(this) as common.UIAbilityContext this.currentContext = getContext(this) as common.UIAbilityContext
@ -143,10 +132,24 @@ export struct ImageKnifeComponent {
return //针对reuse场景不显示历史图片 return //针对reuse场景不显示历史图片
} }
this.pixelMap = pixelMap this.pixelMap = pixelMap
if (typeof this.pixelMap !== 'string' && this.imageKnifeOption.objectFit === ImageFit.Auto) { //针对静态图高度自适应 if (typeof this.pixelMap !== 'string') {
let info = await this.pixelMap.getImageInfo() if (this.imageKnifeOption.objectFit === ImageFit.Auto) {
this.adaptiveWidth = this.currentWidth let info = await this.pixelMap.getImageInfo()
this.adaptiveHeight = info.size.height * this.currentWidth / info.size.width
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) { if (requestSource == ImageKnifeRequestSource.SRC) {
@ -165,4 +168,8 @@ export struct ImageKnifeComponent {
return this.request return this.request
} }
}
interface KeyCanvas {
keyId: string
} }

View File

@ -22,55 +22,38 @@ export interface HeaderOptions {
key: string; key: string;
value: Object; value: Object;
} }
interface AnimatorType {
state?: AnimationStatus @Observed
iterations?: number
reverse?: boolean
onStart?:()=>void
onFinish?:()=>void
onPause?:()=>void
onCancel?:()=>void
onRepeat?:()=>void
}
@ObservedV2
export class AnimatorOption { export class AnimatorOption {
@Trace @Track
state?: AnimationStatus = AnimationStatus.Running state?: AnimationStatus = AnimationStatus.Running
@Trace @Track
iterations?: number = -1 iterations?: number = -1
@Trace @Track
reverse?: boolean = false reverse?: boolean = false
@Trace @Track
onStart?:()=>void onStart?:()=>void
@Trace @Track
onFinish?:()=>void onFinish?:()=>void
@Trace @Track
onPause?:()=>void onPause?:()=>void
@Trace @Track
onCancel?:()=>void onCancel?:()=>void
@Trace @Track
onRepeat?:()=>void onRepeat?:()=>void
constructor(option?:AnimatorType) {
this.state = option?.state
this.iterations = option?.iterations
this.reverse = option?.reverse
this.onStart = option?.onStart
this.onFinish = option?.onFinish
this.onPause = option?.onPause
this.onCancel = option?.onCancel
this.onRepeat = option?.onRepeat
}
} }
interface ImageOption {
@Observed
export class ImageKnifeOption {
// 主图资源 // 主图资源
loadSrc: string | PixelMap | Resource loadSrc: string | PixelMap | Resource = "";
// 占位图 // 占位图
placeholderSrc?: string | PixelMap | Resource placeholderSrc?: string | PixelMap | Resource;
// 失败占位图 // 失败占位图
errorholderSrc?: string | PixelMap | Resource errorholderSrc?: string | PixelMap | Resource;
headerOption?: Array<HeaderOptions>; headerOption?: Array<HeaderOptions>;
// 自定义缓存关键字 // 自定义缓存关键字
signature?: string signature?: string;
// 主图填充效果 // 主图填充效果
objectFit?: ImageFit objectFit?: ImageFit
// 占位图填充效果 // 占位图填充效果
@ -82,65 +65,16 @@ interface ImageOption {
// 缓存策略 // 缓存策略
writeCacheStrategy?: CacheStrategy writeCacheStrategy?: CacheStrategy
// 仅使用缓存加载数据 // 仅使用缓存加载数据
onlyRetrieveFromCache?: boolean; onlyRetrieveFromCache?: boolean = false;
priority?: taskpool.Priority priority?: taskpool.Priority = taskpool.Priority.LOW
context?: common.UIAbilityContext; context?: common.UIAbilityContext;
progressListener?: (progress: number) => void; progressListener?: (progress: number) => void;
transformation?: PixelMapTransformation transformation?: PixelMapTransformation
onLoadListener?: OnLoadCallBack | undefined; onLoadListener?: OnLoadCallBack | undefined;
onComplete?:(event:EventImage | undefined) => void onComplete?:(event:EventImage | undefined) => void
drawingColorFilter?: ColorFilter | drawing.ColorFilter drawingColorFilter?: ColorFilter | drawing.ColorFilter
} constructor() {
@ObservedV2
export class ImageKnifeOption {
// 主图资源
@Trace loadSrc: string | PixelMap | Resource = "";
// 占位图
placeholderSrc?: string | PixelMap | Resource;
// 失败占位图
errorholderSrc?: string | PixelMap | Resource;
headerOption?: Array<HeaderOptions>;
// 自定义缓存关键字
@Trace signature?: string;
// 主图填充效果
@Trace objectFit?: ImageFit
// 占位图填充效果
placeholderObjectFit?: ImageFit
// 错误图填充效果
errorholderObjectFit?: ImageFit
customGetImage?: (context: Context, src: string | PixelMap | Resource) => Promise<ArrayBuffer | undefined>
@Trace border?: BorderOptions
// 缓存策略
writeCacheStrategy?: CacheStrategy
// 仅使用缓存加载数据
onlyRetrieveFromCache?: boolean = false;
priority?: taskpool.Priority = taskpool.Priority.LOW
context?: common.UIAbilityContext;
progressListener?: (progress: number) => void;
@Trace transformation?: PixelMapTransformation
onLoadListener?: OnLoadCallBack | undefined;
onComplete?:(event:EventImage | undefined) => void
drawingColorFilter?: ColorFilter | drawing.ColorFilter
constructor(option?:ImageOption) {
this.loadSrc = option?.loadSrc == undefined ? "" : option?.loadSrc
this.placeholderSrc = option?.placeholderSrc
this.errorholderSrc = option?.errorholderSrc
this.headerOption = option?.headerOption
this.signature = option?.signature
this.objectFit = option?.objectFit
this.placeholderObjectFit = option?.placeholderObjectFit
this.errorholderObjectFit = option?.errorholderObjectFit
this.customGetImage = option?.customGetImage
this.border = option?.border
this.writeCacheStrategy = option?.writeCacheStrategy
this.onlyRetrieveFromCache = option?.onlyRetrieveFromCache
this.priority = option?.priority
this.context = option?.context
this.progressListener = option?.progressListener
this.transformation = option?.transformation
this.onLoadListener = option?.onLoadListener
this.onComplete = option?.onComplete
this.drawingColorFilter = option?.drawingColorFilter
} }
} }

View File

@ -14,11 +14,11 @@
*/ */
import { ImageKnife , ImageKnifeComponent ,ImageKnifeOption } from "@ohos/imageknife" import { ImageKnife , ImageKnifeComponent ,ImageKnifeOption } from "@ohos/imageknife"
@ComponentV2 @Component
export struct IndexComponent { export struct IndexComponent {
@Local imageKnifeOption: ImageKnifeOption = new ImageKnifeOption({ @State imageKnifeOption: ImageKnifeOption = {
loadSrc: $r('app.media.startIcon') loadSrc: $r('app.media.startIcon')
}) }
build() { build() {
Column() { Column() {
Button($r('app.string.Preload')).onClick((event: ClickEvent) => { Button($r('app.string.Preload')).onClick((event: ClickEvent) => {