HarmonyOS Next 动画大全 02-显式动画
前言
上一篇文章我们介绍过属性动画animation
的使用方法,那么本文就来学习和了解一下显示动画animateTo
animateTo
我们称之为显式动画,它本身是一个全局函数,通过调用函数的形式实现动画效果。显式动画animateTo
和之前的属性动画
animation
最大的区别在于 显式动画可以利用本身函数的特性实现多个显式动画连续调用,从而实现连贯性的动画。
基本语法
animateTo(value: AnimateParam, event: () => void): void
解释:
AnimateParam
动画属性,在上一篇文章《HarmonyNext 动画大全 01-属性动画》内有详细介绍过
其中,onFinish 是我们实现连续动画的关键
event
指定动效的闭包函数
基本示例
@Entry
@Component
struct 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
@Component
struct 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
@Component
struct 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。
评论