前言
本文基于Api13
这两天在优化一些功能,发现之前网路库中的oading动画是通过帧动画实现的,而刷新库中的动画却是直接使用的GIF,而到了另一个项目中则又是通过属性动画的方式实现的,索性就针对这几种实现方式简单总结一下,希望可以帮助到有需要的朋友。
首先,我们要知道一点,想要实现一个动态的图片,不仅仅是以上的几种方式,使用lottie也可以实现,所以在实际的开发中,应当根据自身需求需要,选择一种合适的即可。
GIF的实现方式
GIF无疑是实现动态图片的最简单的方式,只需要一个GIF图片便可以搞定,这种方式也是最省心省力的。
只需要把loading的GIF图给Image组件设置即可:
TypeScript
Column() {
Image($r("app.media.loading"))
.width(40)
.height(40)
Text("加载中...")
.margin({ top: 20 })
}
.width(130)
.height(130)
.backgroundColor(Color.White)
.borderRadius(10)
.justifyContent(FlexAlign.Center)
效果如下:

如果你需要控制GIF的播放速度以及暂停,继续播放等动作,可以结合官方推荐的开源库ohos-gif-drawable来实现。
帧动画
帧动画,可以使用ohos.animator来实现,但是我们也可以使用帧动画组件ImageAnimator来实现,它可以实现逐帧播放图片的能力,仅配置需要播放的图片列表就可以轻松完成一个图片的动画效果。
要想实现帧动画的无限次播放,需要设置iterations属性为-1,在组件挂载显示后进行运行帧动画,在组件卸载消失时停止掉针动画。
定义数据
TypeScript
@State state: AnimationStatus = AnimationStatus.Initial
private images: Array<ImageFrameInfo> = [
{ src: $r("app.media.loading001") },
{ src: $r("app.media.loading002") },
{ src: $r("app.media.loading003") },
{ src: $r("app.media.loading004") },
{ src: $r("app.media.loading005") },
{ src: $r("app.media.loading006") },
{ src: $r("app.media.loading007") },
{ src: $r("app.media.loading008") },
{ src: $r("app.media.loading009") },
{ src: $r("app.media.loading010") },
{ src: $r("app.media.loading011") },
{ src: $r("app.media.loading012") }
]
代码实现
TypeScript
Column() {
ImageAnimator()
.images(this.images)
.state(this.state)
.fixedSize(true)
.fillMode(FillMode.None)
.iterations(-1)
.width(40)
.height(40)
Text("加载中...")
.margin({ top: 20 })
.fontColor(Color.White)
}
.width(130)
.height(130)
.backgroundColor("#80000000")
.borderRadius(10)
.justifyContent(FlexAlign.Center)
.onAppear(() => {
this.state = AnimationStatus.Running
})
.onDisAppear(() => {
this.state = AnimationStatus.Stopped
})
运行之后,效果如下:

属性动画
使用属性动画就比较简单了,只需要一张静态的图片便可以搞定,让图片360度无限次旋转即可,需要注意的是,改变旋转角度的属性,应定义在组件加载完成之后,相关代码如下:
TypeScript
@Entry
@Component
struct Index {
@State rotateValue: number = 0
build() {
Column() {
Column() {
Image($r('app.media.loading001'))
.rotate({ angle: this.rotateValue })
.width(40)
.height(40)
.rotate({
angle: this.rotateValue
})
.animation({
duration: 1000,
iterations: -1,
playMode: PlayMode.Normal,
curve: Curve.Linear
})
Text("加载中...")
.margin({ top: 20 })
.fontColor(Color.White)
}
.width(130)
.height(130)
.backgroundColor("#80000000")
.borderRadius(10)
.justifyContent(FlexAlign.Center)
.onAppear(() => {
this.rotateValue = 360
})
}.width('100%')
.height("100%")
.justifyContent(FlexAlign.Center)
}
}
以上的代码和上面的效果差不多,但是需要控制播放的速度,可以通过animation中的duration来控制。
显式动画
以上的效果,我们也可以使用animateTo显示动画来实现,基本参数和属性动画类似,实现方式如下:
TypeScript
@Entry
@Component
struct Index {
@State rotateValue: number = 0
build() {
Column() {
Column() {
Image($r('app.media.loading001'))
.rotate({ angle: this.rotateValue })
.width(40)
.height(40)
Text("加载中...")
.margin({ top: 20 })
.fontColor(Color.White)
}
.width(130)
.height(130)
.backgroundColor("#80000000")
.borderRadius(10)
.justifyContent(FlexAlign.Center)
}.width('100%')
.height("100%")
.justifyContent(FlexAlign.Center)
}
onDidBuild(): void {
animateTo({
duration: 1000,
iterations: -1,
playMode: PlayMode.Normal,
curve: Curve.Linear
}, () => {
this.rotateValue = 360
})
}
}
相关总结
基本上没什么难的,都是非常简单的动画实现,虽然是一个loading动画,但是也可以应用与其他需要动画的地方。
本文标签:HarmonyOS/ArkUI