1、修复了pngj测试页面,快速点击导致应用闪退的问题 Signed-off-by: 明月清风 <2928139825@qq.com> |
||
---|---|---|
AppScope | ||
entry | ||
gpu_transform | ||
hvigor | ||
imageknife | ||
screenshot | ||
.eslintignore | ||
.gitignore | ||
CHANGELOG.md | ||
LICENSE | ||
NOTICE | ||
OAT.xml | ||
README.OpenSource | ||
README.md | ||
build-profile.json5 | ||
hvigorfile.js | ||
hvigorw | ||
hvigorw.bat | ||
oh-package.json5 |
README.md
ImageKnife
专门为OpenHarmony打造的一款图像加载缓存库,致力于更高效、更轻便、更简单。
简介
本项目基于开源库 Glide 进行OpenHarmony的自研版本:
- 支持内存缓存,使用LRUCache算法,对图片数据进行内存缓存。
- 支持磁盘缓存,对于下载图片会保存一份至磁盘当中。
- 支持进行图片变换: 支持图像像素源图片变换效果。
- 支持用户配置参数使用:( 例如:配置是否开启一级内存缓存,配置磁盘缓存策略,配置仅使用缓存加载数据,配置图片变换效果,配置占位图,配置加载失败占位图等)。
- 推荐使用ImageKnifeComponent组件配合ImageKnifeOption参数来实现功能。
- 支持用户自定义配置实现能力参考ImageKnifeComponent组件中对于入参ImageKnifeOption的处理。

下载安装
ohpm install @ohos/imageknife
使用说明
1.依赖配置
在项目中entry/oh-package.json5中做如下修改,然后点击Sync Now:
{
"name": "entry",
"version": "1.0.0",
"description": "Please describe the basic information.",
"main": "",
"author": "",
"license": "",
"dependencies": {
"@ohos/imageknife": "^2.0.2"
}
}
在entry\src\main\ets\entryability\EntryAbility.ts中做如下配置初始化全局ImageKnife实例:
import UIAbility from '@ohos.app.ability.UIAbility';
import window from '@ohos.window';
import { ImageKnife } from '@ohos/imageknife'
export default class EntryAbility extends UIAbility {
onWindowStageCreate(windowStage: window.WindowStage) {
windowStage.loadContent('pages/Index', (err, data) => {
});
//初始化全局ImageKnife
globalThis.ImageKnife = ImageKnife.with(this.context);
}
}
2.加载普通图片
接下来我们来写个简单实例看看:
import { ImageKnifeComponent, ImageKnifeOption } from '@ohos/imageknife'
@Entry
@Component
struct Index {
@State message: string = 'Hello World'
@State option: ImageKnifeOption = {
loadSrc: $r('app.media.icon')
}
build() {
Row() {
Column() {
Text(this.message)
.fontSize(50)
.fontWeight(FontWeight.Bold)
ImageKnifeComponent({ imageKnifeOption: this.option })
.width(300)
.height(300)
}.width('100%')
}.height('100%')
}
}
非常简单,仅需定义一个ImageKnifeOption数据对象,然后在你需要的UI位置,加入ImageKnifeComponent自定义组件就可以加载出一张图像了。
3.加载SVG图片
加载svg其实和普通流程没有区别,只要将 loadSrc: $r('app.media.jpgSample'),
改成一张 loadSrc: $r('app.media.svgSample'),
svg类型图片即可。
目前加载SVG图片解析依赖了 SVG三方库,由于目前该库还无法解析mask标签,所以这里大家需要留意一下。
4.加载GIF图片
加载GIF其实和普通流程也没有区别只要将 loadSrc: $r('app.media.jpgSample'),
改成一张 loadSrc: $r('app.media.gifSample'),
GIF图片即可。
但是解析gif图片属于耗时操作,所以我们需要将其放入子线程操作。 **这里我们需要在页面的创建和销毁上添加一个worker子线程操作。 **
import router from '@ohos.router'
import { ImageKnifeComponent, ImageKnifeOption, } from '@ohos/imageknife'
import worker from '@ohos.worker';
@Entry
@Component
struct IndexFunctionDemo {
private globalGifWorker: any = undefined
@State imageKnifeOption1: ImageKnifeOption = {
loadSrc: $r('app.media.icon'),
placeholderSrc: $r('app.media.icon_loading'),
errorholderSrc: $r('app.media.icon_failed')
};
@State imageKnifeOption2: ImageKnifeOption = {
loadSrc: $r('app.media.icon'),
placeholderSrc: $r('app.media.icon_loading'),
errorholderSrc: $r('app.media.icon_failed')
};
build() {
Scroll() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Text("简单示例1:加载一张本地png图片").fontSize(15)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button("加载PNG")
.onClick(() => {
this.imageKnifeOption1 = {
loadSrc: $r('app.media.pngSample'),
placeholderSrc: $r('app.media.icon_loading'),
errorholderSrc: $r('app.media.icon_failed')
}
}).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink)
Text("简单示例2:加载一张网络gif图片").fontSize(15)
Text("gif解析在子线程,请在页面构建后创建worker,注入imageknife").fontSize(15)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button("加载GIF")
.onClick(() => {
this.imageKnifeOption2 = {
loadSrc: 'https://gd-hbimg.huaban.com/e0a25a7cab0d7c2431978726971d61720732728a315ae-57EskW_fw658',
placeholderSrc: $r('app.media.icon_loading'),
errorholderSrc: $r('app.media.icon_failed'),
displayProgress: true,
}
}).margin({ top: 5, left: 3 })
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption2 }).width(300).height(300)
}.width('100%').backgroundColor(Color.Pink)
Flex({ direction: FlexDirection.Row, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Button("ImageKnife测试目录页面")
.onClick(() => {
console.log("pages/imageknifeTestCaseIndex 页面跳转")
router.pushUrl({ url: "pages/imageknifeTestCaseIndex" });
}).margin({ top: 15 })
}.width('100%').height(60).backgroundColor(Color.Pink)
}
}
.width('100%')
.height('100%')
}
aboutToAppear() {
this.globalGifWorker = new worker.ThreadWorker('entry/ets/workers/GifLoadWorker.ts')
// gif解析在子线程,请在页面构建后创建worker,注入imageknife
globalThis.ImageKnife.setGifWorker(this.globalGifWorker)
}
aboutToDisappear() {
// 页面销毁 销毁worker
if (this.globalGifWorker) {
this.globalGifWorker.terminate();
}
}
}
5.创建worker
由于使用到了worker,目前worker创建只能在entry里面,所以我这边着重讲一下worker配置的流程。
在entry目录上:点击鼠标右键 --> New --> Worker

在弹出窗口中填入即将创建的worker的名称GifLoadWorker,点击弹窗右下角Finish,

DevEco将自动在entry/src/main/ets/workers目录下生成GifLoadWorker.ts文件,并在其中生成模板代码

同时entry模块下build-profile.json5也会自动生成新建的worker的配置信息

接下来我们在GifLoadWorker.ts中导入gif处理方法
import { gifHandler } from '@ohos/imageknife/GifWorker'
同时设置
workerPort.onmessage = gifHandler
经过了上面的配置,就配置好了worker,GIF图片加载就能顺利进行了。 如果GIF加载未成功,可以检查一下worker配置是否完成,或者参考entry/src/main/ets/pages/testGifLoadWithWorkerPage.ets中的gif加载写法。
进阶使用
如果简单的加载一张图像无法满足需求,我们可以看看ImageKnifeOption这个类提供了哪些扩展能力。
ImageKnifeOption参数列表
参数名称 | 入参内容 | 功能简介 |
---|---|---|
loadSrc | string \ | PixelMap \ |
mainScaleType | ScaleType | 设置主图展示样式(可选) |
strategy | DiskStrategy | 设置磁盘缓存策略(可选) |
dontAnimateFlag | boolean | gif加载展示一帧(可选) |
placeholderSrc | PixelMap \ | Resource |
placeholderScaleType | ScaleType | 设置占位图展示样式(可选) |
errorholderSrc | PixelMap \ | Resource |
errorholderSrcScaleType | ScaleType | 设置失败占位图展示样式(可选) |
retryholderSrc | PixelMap \ | Resource |
retryholderScaleType | ScaleType | 设置重试占位图展示样式(可选) |
thumbSizeMultiplier | number 范围(0,1] | 设置缩略图占比(可选) |
thumbSizeDelay | number | 设置缩略图展示时间(可选) |
thumbSizeMultiplierScaleType | ScaleType | 设置缩略图展示样式(可选) |
displayProgress | boolean | 设置是否展示下载进度条(可选) |
canRetryClick | boolean | 设置重试图层是否点击重试(可选) |
onlyRetrieveFromCache | boolean | 仅使用缓存加载数据(可选) |
isCacheable | boolean | 是否开启一级内存缓存(可选) |
gif | { // 返回一周期动画gif消耗的时间 loopFinish?: (loopTime?) => void // gif播放速率相关 speedFactory?: number // 直接展示gif第几帧数据 seekTo?: number } |
GIF播放控制能力(可选) |
transformation | BaseTransform | 单个变换(可选) |
transformations | Array<BaseTransform> | 多个变换,目前仅支持单个变换(可选) |
allCacheInfoCallback | IAllCacheInfoCallback | 输出缓存相关内容和信息(可选) |
drawLifeCycle | IDrawLifeCycle | 用户自定义实现绘制方案(可选) |
其他参数只需要在ImageKnifeOption对象上按需添加即可。
这里我们着重讲一下自定义实现绘制方案。为了增强绘制扩展能力,目前ImageKnifeComponent使用了Canvas的渲染能力作为基础。在此之上为了抽象组件绘制表达。我将图像的状态使用了 IDrawLifeCycle绘制生命周期进行表达,
大致流程 展示占位图->展示网络加载进度->展示缩略图->展示主图->展示重试图层->展示失败占位图

ImageKnifeComponent内部,责任链实现。 用户参数设置->全局参数设置->自定义组件内部设置
采用责任链的好处是,用户可以通过自定义绘制,重新绘制图层。如果不想绘制也可以通过预制回调获取绘制流程信息。

场景1:默认的展示不满足需求,需要加个圆角效果。
代码如下:
import { ImageKnifeComponent } from '@ohos/imageknife'
import { ImageKnifeOption } from '@ohos/imageknife'
import { ImageKnifeDrawFactory } from '@ohos/imageknife'
@Entry
@Component
struct Index {
@State imageKnifeOption1: ImageKnifeOption = {
// 加载一张本地的jpg资源(必选)
loadSrc: $r('app.media.jpgSample'),
// 占位图使用本地资源icon_loading(可选)
placeholderSrc: $r('app.media.icon_loading'),
// 失败占位图使用本地资源icon_failed(可选)
errorholderSrc: $r('app.media.icon_failed'),
// 绘制圆角30,边框5,边框"#ff00ff".用户自定义绘制(可选)
drawLifeCycle:ImageKnifeDrawFactory.createRoundLifeCycle(5,"#ff00ff",30)
};
build(){
Scroll() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
ImageKnifeComponent({ imageKnifeOption: this.imageKnifeOption1 })
.width(300)
.height(300)
}
}
.width('100%')
.height('100%')
}
}
ImageKnifeDrawFactory.createRoundLifeCycle(5,"#ff00ff",30)
我们深入查看源码可以发现,实际上是对IDrawLifeCycle接口的部分实现,这里我介绍一下IDrawLifeCycle。
IDrawLifeCycle的返回值代表事件是否被消费,如果被消费接下来组件内部就不会处理,如果没被消费就会传递到下一个使用者。目前消费流程(用户自定义-> 全局配置定义->组件内部默认定义)*
所以我们在当数据是一张PixelMap的时候(目前jpg png bmp webp svg返回的都是PixelMap,gif返回GIFFrame数组),我们返回了true。消费了事件,代表这个绘制流程用户自定义完成。

由于IDrawLifeCycle实现较为冗长,我们封装了ImageKnifeDrawFactory工厂,提供了网络下载百分比效果、圆角、椭圆添加边框等能力。下面我们就再看看使用工厂封装之后的场景代码。
场景2: 网络下载百分比效果展示
当进行加载网络图片时,可能需要展示网络下载百分比动画。但是默认的动画又不能满足需求,这个时候我们就需要自定义网络下载百分比效果。代码如下:
import AbilityStage from '@ohos.application.AbilityStage'
import { ImageKnife, ImageKnifeDrawFactory } from '@ohos/imageknife'
import ArkWorker from '@ohos.worker'
export default class MyAbilityStage extends AbilityStage {
onCreate() {
globalThis.ImageKnife = ImageKnife.with(this.context);
// 全局配置网络加载进度条
globalThis.ImageKnife.setDefaultLifeCycle(ImageKnifeDrawFactory.createProgressLifeCycle("#10a5ff", 0.5))
}
}
这里大家可能会问,为什么会将这个IDrawLifeCycle放在AbilityStage里面实现?
这是因为网络下载百分比进度很多时候都是全局通用,如果有需要全局配置的自定义展示方案。推荐在AbilityStage里面,往ImageKnife的setDefaultLifeCycle函数中注入,即可将ImageKnifeComponent中的默认绘制方案替换。
在这里我们实现的效果如下图所示。

高级用法
以上简单使用和进阶使用都是经过一层自定义组件封装之后形成的,RequestOption封装成了ImageKnifeOption,绘制部分封装成了自定义组件ImageKnifeComponent。
如果用户其实并不关心绘制部分,或者说想用自己的通用方案对自定义组件ImageKnifeComponent重构都是可以的。
下面我们会着重指导用户如何复用图片加载逻辑,重构自定义组件ImageKnifeComponent。
首先我们先看看RequestOption构建的内容,如下所示:
数据加载
RequestOption构建:
请查阅下文接口内容:RequestOption接口方法
了解了RequestOption的参数内容后,我们可以参考ImageKnifeComponent组件代码进行分析。
从imageKnifeExecute()
函数入口,首先我们需要构建一个RequestOption对象,let request = new RequestOption()
,
接下来就是按需配置request对象的内容,最后使用 globalThis.ImageKnife.call(request)
发送request执行任务即可。
是不是很简单,而其实最重要的内容是就是: 按需配置request对象的内容 为了更好理解,我举例说明一下:
场景一: 简单加载一张图片
let request = new RequestOption();
// (必传)
request.load("图片url")
// (可选 整个request监听回调)
.addListener((err, data) => {
// data 是ImageKnifeData对象
if(data.isPixelMap()){
// 这样就获取到了目标PixelMap
let pixelmap = data.drawPixleMap.imagePixelMap;
}
return false;
})
let compSize = {
width: this.currentWidth,
height:this.currentHeight
}
// (必传)这里setImageViewSize函数必传组件大小,因为涉及到图片变换效果都需要适配图像源和组件大小
request.setImageViewSize(compSize)
// 最后使用ImageKnife的call函数调用request即可
globalThis.ImageKnife.call(request)
其他场景,可以按需加载
比如我需要配置 占位图 只需要 在request对象创建好之后,调用 placeholder 函数即可
request.placeholder(this.imageKnifeOption.placeholderSrc, (data) => {
console.log('request.placeholder callback')
this.displayPlaceholder(data)
})
再比如 我对缓存配置有要求,我要禁用内存缓存,调用 skipMemoryCache 函数即可
request.skipMemoryCache(true)
这里只是简单介绍部分使用,更多的内容请参考 按需加载 原则,并且可以参考ImageKnifeComponent源码或者根据文档自行探索实现。
接口说明
RequestOption用户配置参数
方法名 | 入参 | 接口描述 |
---|---|---|
load(src: string \ | PixelMap \ | Resource) |
setImageViewSize(imageSize: { width: number, height: number }) | { width: number, height: number } | 传入显示图片组件的大小,变换的时候需要作为参考 |
diskCacheStrategy(strategy: DiskStrategy) | DiskStrategy | 配置磁盘缓存策略 NONE SOURCE RESULT ALL AUTOMATIC |
placeholder(src: PixelMap \ | Resource, func?: AsyncSuccess) | src: PixelMap \ |
errorholder(src: PixelMap \ | Resource, func?: AsyncSuccess) | src: PixelMap \ |
retryholder(src: PixelMap \ | Resource, func?: AsyncSuccess) | src: PixelMap \ |
addListener(func: AsyncCallback) | func: AsyncCallback | 配置整个监听回调,数据正常加载返回,加载失败返回错误信息 |
thumbnail(sizeMultiplier:number, func?: AsyncSuccess) | sizeMultiplier:number, func?: AsyncSuccess | 设置缩略图比例,缩略图返回后,加载并展示缩略图 |
addProgressListener(func?: AsyncSuccess) | func?: AsyncSuccess | 设置网络下载百分比监听,返回数据加载百分比数值 |
addRetryListener(func?: AsyncSuccess) | func?: AsyncSuccess | 设置重试监听 |
addAllCacheInfoCallback(func: IAllCacheInfoCallback) | func: IAllCacheInfoCallback | 设置获取所有缓存信息监听 |
skipMemoryCache(skip: boolean) | skip: boolean | 配置是否跳过内存缓存 |
retrieveDataFromCache(flag: boolean) | flag: boolean | 配置仅从缓存中加载数据 |
同时支持图片变换相关接口。
ImageKnife 启动器/门面类
方法名 | 入参 | 接口描述 |
---|---|---|
call(request: RequestOption) | request: RequestOption | 根据用户配置参数具体执行加载流程 |
preload(request: RequestOption) | request: RequestOption | 根据用户配置参数具体执行预加载流程 |
缓存策略相关
使用方法 | 类型 | 策略描述 |
---|---|---|
request.diskCacheStrategy(new ALL()) | ALL | 表示既缓存原始图片,也缓存转换过后的图片 |
request.diskCacheStrategy(new AUTOMATIC()) | AUTOMATIC | 表示尝试对本地和远程图片使用适合的策略 |
request.diskCacheStrategy(new DATA()) | DATA | 表示只缓存原始图片 |
request.diskCacheStrategy(new NONE()) | NONE | 表示不缓存任何内容 |
request.diskCacheStrategy(new RESOURCE()) | RESOURCE | 表示只缓存转换过后的图片 |
ScaleType类型展示效果
使用方法 | 类型 | 策略描述 |
---|---|---|
ScaleType.FIT_START | int | 图像位于用户设置组件左上角显示,图像会缩放至全部展示 |
ScaleType.FIT_END | int | 图像位于用户设置组件右下角显示,图像会缩放至全部展示 |
ScaleType.FIT_CENTER | int | 图像位于用户设置组件居中,图像会缩放至全部展示 |
ScaleType.CENTER | int | 图像居中展示,不缩放 |
ScaleType.CENTER_CROP | int | 图像的宽高长度,短的部分缩放至组件大小,超出的全部裁剪 |
ScaleType.FIT_XY | int | 图像拉伸至组件大小 |
ScaleType.CENTER_INSIDE | int | 如果图像大于组件则执行FIT_CENTER,小于组件则CENTER |
ScaleType.NONE | int | 如果不想适配,直接展示原图大小 |
图片变换相关
使用方法 | 类型 | 相关描述 |
---|---|---|
request.centerCrop() | CenterCrop | 可以根据图片文件,目标显示大小,进行对应centerCrop |
request.centerInside() | CenterInside | 可以根据图片文件,目标显示大小,进行对应centerInside |
request.fitCenter() | FitCenter | 可以根据图片文件,目标显示大小,进行对应fitCenter |
request.blur() | BlurTransformation | 模糊处理 |
request.brightnessFilter() | BrightnessFilterTransformation | 亮度滤波器 |
request.contrastFilter() | ContrastFilterTransformation | 对比度滤波器 |
request.cropCircle() | CropCircleTransformation | 圆形剪裁显示 |
request.cropCircleWithBorder() | CropCircleWithBorderTransformation | 圆环展示 |
request.cropSquare() | CropSquareTransformation | 正方形剪裁 |
request.crop() | CropTransformation | 自定义矩形剪裁 |
request.grayscale() | GrayscaleTransformation | 灰度级转换 |
request.invertFilter() | InvertFilterTransformation | 反转滤波器 |
request.pixelationFilter() | PixelationFilterTransformation | 像素化滤波器 |
request.rotateImage() | RotateImageTransformation | 图片旋转 |
request.roundedCorners() | RoundedCornersTransformation | 圆角剪裁 |
request.sepiaFilter() | SepiaFilterTransformation | 乌墨色滤波器 |
request.sketchFilter() | SketchFilterTransformation | 素描滤波器 |
request.mask() | MaskTransformation | 遮罩 |
request.swirlFilter() | SwirlFilterTransformation | 扭曲滤波器 |
request.kuwaharaFilter() | KuwaharaFilterTransform | 桑原滤波器 |
request.toonFilter() | ToonFilterTransform | 动画滤波器 |
request.vignetteFilter() | VignetteFilterTransform | 装饰滤波器 |

约束与限制
在下述版本验证通过:
DevEco Studio 4.0 Release(4.0.3.413)--SDK( 4.0.10.3)原型机:NOH-AN00 204.0.0.62(SP1C00E62R1P11)
目录结构
/imageknife/src/
- main/ets/components
- cache # 缓存相关内容
- diskstrategy # 缓存策略
- key # 缓存key生成策略
- Base64.ets # Base64算法
- CustomMap.ets # 自定义Map封装
- DiskCacheEntry.ets # 磁盘缓存entry
- DiskLruCache.ets # 磁盘LRU缓存策略
- FileReader.ets # 文件读取相关
- FileUtils.ets # 文件工具类
- LruCache.ets # 内存LRU缓存策略
- Md5.ets # MD5算法
- imageknife # imageknife主要内容
- compress # 压缩相关
- constants # 常量相关
- entry # 部分数据结构
- holder # 占位图相关解析
- interface # 接口相关
- networkmanage # 网络相关
- pngj # pngj相关
- requestmanage # imageknife请求相关
- resourcemanage # 本地资源解析相关
- transform # 图片变换相关
- utils # 工具类相关
- ImageKnife.ets # imageknife门面,app持久化类
- ImageKnifeData.ets # 数据封装
- ImageKnifeComponent.ets # 自定义控件封装
- ImageKnifeDrawFactory.ets # IDrawLifeCycle用户自定义实现
- ImageKnifeOption.ets # 用户传参数封装
- RequestOption.ets # 用户设置参数封装
/entry/src/
- main/ets
- entryability
- CustomEngineKeyImpl.ets
- EntryAbility.ts
- pages # 测试page页面列表
- basicTestFeatureAbilityPage.ets # 测试列表加载
- basicTestFileIOPage.ets # 测试fileio
- basicTestMediaImage.ets # 测试媒体image
- basicTestResourceManagerPage.ets # 测试本地资源解析
- compressPage.ets # 压缩页面
- cropImagePage2.ets # 手势裁剪页面
- frescoImageTestCasePage.ets # 测试属性动画组件切换
- frescoRetryTestCasePage.ets # 测试ImageKnifeComponent加载失败重试
- gifTestCasePage.ets # 测试gif解析页面
- svgTestCasePage.ets # 测试svg解析页面
- imageknifeTestCaseIndex.ets # 测试用例页面入口
- index.ets # 程序入口页面
- loadNetworkTestCasePage.ets # 网络加载测试
- loadResourceTestCasePage.ets # 本地加载测试
- showErrorholderTestCasePage.ets # 加载失败占位图测试
- storageTestDiskLruCache.ets # 磁盘缓存测试
- storageTestLruCache.ets # 内存缓存测试
- testAllCacheInfoPage.ets # 所有缓存信息获取测试
- testGifDontAnimatePage.ets # gif加载静态图片测试
- testImageKnifeOptionChangedPage.ets # 数据切换测试
- testImageKnifeOptionChangedPage2.ets # 数据切换测试,部分变换
- testImageKnifeOptionChangedPage3.ets # 数据切换测试,组件动画
- testImageKnifeOptionChangedPage4.ets # 数据切换测试,内容动画
- testImageKnifeOptionChangedPage5.ets # 数据切换测试,ImageKnifeDrawFactory封装圆角圆环边框等
- testPreloadPage.ets # 预加载测试
- transformPixelMapPage.ets # 所有类型变换测试
- testSingleFrameGifPage.ets # 单帧gif加载测试
- testGifLoadWithWorkerPage.ets # gif加载有无worker的影响测试
-workers
- GifLoadWorkers.ts # gif子线程解析
- MyWorker.ts # worker使用示例
- PngLoadWorker.ts # png子线程解析
贡献代码
使用过程中发现任何问题都可以提 issue 给我们,当然,我们也非常欢迎你给我们发 PR 。
开源协议
本项目基于 Apache License 2.0 ,请自由的享受和参与开源。
遗留问题
1.目前只支持一种图片变换效果。
2.目前svg和gif动图不支持变换效果。
3.svg解析目前不支持mask标签。