HarmonyOS Next 动画大全 02-显式动画
前言
上一篇文章我们介绍过属性动画animation的使用方法,那么本文就来学习和了解一下显示动画animateTo
animateTo
我们称之为显式动画,它本身是一个全局函数,通过调用函数的形式实现动画效果。显式动画animateTo和之前的属性动画
animation最大的区别在于 显式动画可以利用本身函数的特性实现多个显式动画连续调用,从而实现连贯性的动画。
基本语法
animateTo(value: AnimateParam, event: () => void): void
解释:
AnimateParam 动画属性,在上一篇文章《HarmonyNext 动画大全 01-属性动画》内有详细介绍过
其中,onFinish 是我们实现连续动画的关键
event 指定动效的闭包函数
基本示例
@Entry@Componentstruct Index { @State scaleXY: number = 1
build() { Column() { Button("点我就变大啦") .scale({ x: this.scaleXY, y: this.scaleXY }) .onClick(() => { // 显式动画 animateTo({ // 1 指定动画参数 duration: 1000 }, () => { // 2 指定动效的闭包函数 this.scaleXY = 2 }) }) } .width("100%") .height("100%") .padding(40) }}
复制代码
代码解释:
可以看到 animateTo就是一个全局函数,可以直接调用
duration: 1000 表示动画参数,动画的持续时间为 1s
this.scaleXY = 2 放在 animateTo的第二个参数上,回调函数,也是在这里指定要具体执行的动画效果
至此,我们发现 显式动画 animateTo 和 之前的属性动画 animation 没有太大区别。 对的,因为他们两个最大的区别就在于 animateTo 可以比较方便实现连续多个动画效果。
连续多个动画效果
如下图:
可以看到以上动画其实是有多个动画效果组合在一起的。如
左上角 -> 右上角
右上角 -> 右下角
右下角 -> 左下角
左下角 -> 左上角
我们思考:该如何实现呢?
答案是:onFinish。 onFinish 是动画参数中的一个属性,表示动画执行完毕。
onFinish
当动画执行完毕时,便会自动触发 onFinish里面的逻辑
@Entry@Componentstruct Index { @State x: number = 0 @State y: number = 0
build() { Column() { Row() .width(100) .height(100) .backgroundColor("#499C54")// tips: translate 表示设置位移 .translate({ x: this.x, y: this.y }) .onClick(() => { animateTo({ // 动画执行完毕触发 onFinish: () => { AlertDialog.show({ message: "动画执行完毕" }) } }, () => { this.x = 100 this.y = 0 }) }) } .width("100%") .height("100%") .alignItems(HorizontalAlign.Start)
}}
复制代码
因此,当我们想要实现连续执行多个动画时,就不断往onFinish里面套娃即可
@Entry@Componentstruct Index { @State x: number = 0 @State y: number = 0
build() { Column() { Row() .width(100) .height(100) .backgroundColor("#499C54") .translate({ x: this.x, y: this.y }) .onClick(() => { // 1 左上角 -> 右上角 animateTo({ onFinish: () => { // 2 右上角 -> 右下角 animateTo({ onFinish: () => { // 3 右下角 -> 左下角 animateTo({ onFinish: () => { // 4 左下角 -> 左上角 animateTo({}, () => { this.x = 0 this.y = 0 }) } }, () => { this.x = 0 this.y = 100 }) } }, () => { this.x = 100 this.y = 100 }) } }, () => { this.x = 100 this.y = 0 }) }) } .width("100%") .height("100%") .alignItems(HorizontalAlign.Start)
}}
复制代码
以上这个代码,就可以实现连续动画了。
回调函数地狱
但是,这个代码结构,妈妈看到了很难不夸你写得好
以上结构已经形成了一个回调函数地狱了,小伙伴们~😂
解决回调函数地狱
有开发经验的小伙们应该可以马上想到解决方法
promise
async 和 await
对的,回调函数地狱可以靠这两个老哥来解决。
先拿 animateTo 和 Promise 做一个封装
const animateToPromise = (option: AnimateParam, fn: Function) => { const promise: Promise<undefined> = new Promise((resolve: Function) => { option.onFinish = () => { resolve(); }; animateTo(option, () => { fn(); }); }); return promise;};
复制代码
最后再来看解决后的版本
Row() {
} .width(100) .height(100) .backgroundColor("#499C54") .translate({ x: this.x, y: this.y }) .onClick(async () => { // 1 左上角 -> 右上角 await animateToPromise({}, () => { this.x = 100 this.y = 0 }) // 2 右上角 -> 右下角 await animateToPromise({}, () => { this.x = 100 this.y = 100 }) // 3 右下角 -> 左下角 await animateToPromise({}, () => { this.x = 0 this.y = 100 }) // 4 左下角 -> 左上角 await animateToPromise({}, () => { this.x = 0 this.y = 0 }) })
复制代码
可以看到,封装后的代码,要简洁不少
小结
animateTo 适合用在连续多个动画效果上
animateTo 可以搭配promise 和async、await 解决回调地狱的问题
由于篇幅问题,这里没有直接介绍 promise 和 async。
评论