在最近的项目开发工作中,我频繁需要为界面元素添加过渡动画效果,以提升用户体验。在这个过程中,我接触到了 ArkTS 提供的 animateTo
全局显式动画接口。它为由于闭包代码导致的状态变化插入过渡动效提供了便捷的方式,能让布局类的宽高变化以及内容呈现出流畅的动画效果。然而,这个接口的使用细节和相关参数较多,文档虽然详细但较为零散,对于初学者来说理解和掌握起来有一定难度。因此,我决定撰写这篇博客,将自己的学习经验和理解整理成一份自学指南,希望能帮助其他开发者更快速、深入地掌握 animateTo
接口的使用。
animateTo
接口概述animateTo
接口提供了一种显式的方式来为状态变化添加过渡动画。它支持属性动画、布局类的宽高变化动画等。不过需要注意的是,默认情况下内容(如文字、Canvas 内容)会直接到达终点状态,若要让内容跟随宽高变化,可以使用 renderFit
属性进行配置。
UIContext
中的 animateTo
来明确 UI 的执行上下文。typescript
animateTo(value: AnimateParam, event: () => void): void
value
:AnimateParam
类型,必填,用于设置动画效果相关参数。event
:() => void
类型,必填,指定动效的闭包函数,在闭包函数中导致的状态变化系统会自动插入过渡动画。AnimateParam
对象详细说明AnimateParam
对象包含了多个用于配置动画效果的参数,下面是各个参数的详细介绍:
duration
number
tempo
number
curve
Curve | ICurve9+ | string
Curve.EaseInOut
。delay
number
(-∞, +∞)
。 delay >= 0
为延迟播放,delay < 0
表示提前播放。对于 delay < 0
的情况:当 delay
的绝对值小于实际动画时长,动画将在开始后第一帧直接运动到 delay
绝对值的时刻的状态;当 delay
的绝对值大于等于实际动画时长,动画将在开始后第一帧直接运动到终点状态。其中实际动画时长等于单次动画时长乘以动画播放次数。iterations
number
[-1, +∞)
。playMode
PlayMode
PlayMode.Normal
。 PlayMode.Normal
和 PlayMode.Alternate
,此场景下动画的第一轮是正向播放的。如使用 PlayMode.Reverse
和 PlayMode.AlternateReverse
,则动画的第一轮是逆向播放的,在动画刚开始时会跳变到终止状态,然后逆向播放动画。PlayMode.Alternate
或 PlayMode.AlternateReverse
时,开发者应保证动画最终状态和状态变量的取值一致,即应保证动画的最后一轮是正向播放的。使用 PlayMode.Alternate
时,iterations
应为奇数。使用 PlayMode.AlternateReverse
时,iterations
应为偶数。PlayMode.Reverse
,此场景下不仅会导致动画刚开始就跳变到终止状态,也会导致动画最终状态和状态变量的取值不同。onFinish
() => void
finishCallbackType11+
FinishCallbackType
onFinish
回调的类型。默认值为 FinishCallbackType.REMOVED
。 FinishCallbackType
说明: REMOVED
:当整个动画结束并立即删除时,将触发回调。LOGICALLY
:当动画在逻辑上处于下降状态,但可能仍处于其长尾状态时,将触发回调。expectedFrameRateRange11+
ExpectedFrameRateRange
ExpectedFrameRateRange
说明: min
:期望的最小帧率。max
:期望的最大帧率。expected
:期望的最优帧率。duration
为 0 的动画闭包函数中改变属性,可以实现停止该属性动画的效果。onAppear
中实现动画的创建。不推荐在 aboutToAppear
、aboutToDisappear
中调用动画。因为在 aboutToAppear
中调用动画,自定义组件内的 build
还未执行,内部组件还未创建,动画时机过早,动画属性没有初值无法对组件产生动画;执行 aboutToDisappear
时,组件即将销毁,不能在 aboutToDisappear
里面做动画。animateTo
实现组件消失动画效果。onAppear
中执行// xxx.ets
@Entry
@Component
struct AnimateToExample {
@State widthSize: number = 300
@State heightSize: number = 120
@State rotateAngle: number = 0
private flag: boolean = true
build() {
Column() {
Button('change size')
.width(this.widthSize)
.height(this.heightSize)
.margin(40)
.onClick(() => {
if (this.flag) {
// 建议使用this.getUIContext()?.animateTo()
animateTo({
duration: 2500,
curve: Curve.EaseIn,
iterations: 4,
playMode: PlayMode.Normal,
onFinish: () => {
console.info('play end')
}
}, () => {
this.widthSize = 180
this.heightSize = 80
})
} else {
// 建议使用this.getUIContext()?.animateTo()
animateTo({}, () => {
this.widthSize = 300
this.heightSize = 120
})
}
this.flag = !this.flag
})
Button('stop rotating')
.margin(60)
.rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle })
.onAppear(() => {
// 组件出现时开始做动画
// 建议使用this.getUIContext()?.animateTo()
animateTo({
duration: 1500,
curve: Curve.EaseIn,
delay: 600,
iterations: -1, // 设置-1表示动画无限循环
playMode: PlayMode.Alternate,
expectedFrameRateRange: {
min: 15,
max: 130,
expected: 70,
}
}, () => {
this.rotateAngle = 120
})
})
.onClick(() => {
// 建议使用this.getUIContext()?.animateTo()
animateTo({ duration: 0 }, () => {
// this.rotateAngle之前为120,在duration为0的动画中修改属性,可以停止该属性之前的动画,按新设置的属性显示
this.rotateAngle = 0
})
})
}.width('100%').margin({ top: 10 })
}
}
// xxx.ets
@Entry
@Component
struct AttrAnimationExample {
@State heightSize: number = 120;
@State isShow: boolean = true;
@State count: number = 0;
private isToBottom: boolean = true; // 向下
build() {
Column() {
if (this.isShow) {
Column()
.width(220)
.height(this.heightSize)
.backgroundColor('green')
.onClick(() => {
// 建议使用this.getUIContext()?.animateTo()
animateTo({
duration: 2200,
curve: Curve.EaseInOut,
iterations: 1,
playMode: PlayMode.Normal,
onFinish: () => {
this.count--;
if (this.count == 0 && !this.isToBottom) { // 组件只有在向下做完动画才会消失
this.isShow = false;
}
}
}, () => {
this.count++;
if (this.isToBottom) {
this.heightSize = 70;
} else {
this.heightSize = 120;
}
this.isToBottom = !this.isToBottom;
})
})
}
}.width('100%').height('100%').margin({ top: 10 })
.justifyContent(FlexAlign.End)
}
}
通过以上的介绍和示例,相信你已经对 ArkTS 的 animateTo
接口有了更深入的了解。在实际开发中,你可以根据具体需求灵活配置 AnimateParam
对象的参数,实现各种炫酷的动画效果。
最后如果这篇文章对你有帮助,希望您能关注,点赞,加收藏哦~~~~
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。