#跟着若城学鸿蒙# 动画篇-显式动画(animateTo)详解
ArkUI中的显式动画(animateTo)详解
概述
ArkUI_NativeAnimateAPI_1是ArkUI提供的一组Native侧动画接口,包括显式动画、关键帧动画以及创建和销毁动画对象的功能。这些接口允许开发者通过编程方式控制动画效果,实现丰富的用户界面交互。
显式动画(animateTo)是ArkUI中一种强大的动画实现方式,它通过闭包内改变属性引起的界面变化来产生动画效果。与属性动画不同,显式动画作用于出现消失转场,是通用函数,对闭包前界面和闭包中的状态变量引起的界面之间的差异做动画。它支持多次调用和嵌套使用。
基本用法
animateTo接口的基本语法如下:
animateTo(value: AnimateParam, event: () => void): void
其中:
value
:设置动画效果相关参数event
:指定动效的闭包函数,在闭包函数中导致的状态变化系统会自动插入过渡动画
参数说明
AnimateParam对象包含以下可配置参数:
参数名 | 类型 | 描述 |
---|---|---|
duration | number | 动画播放时长 |
curve | Curve | 动画曲线类型 |
delay | number | 动画延迟执行的时长 |
iterations | number | 动画播放次数 |
playMode | PlayMode | 动画播放模式 |
onFinish | () => void | 动画播放完成回调 |
使用示例
基础示例
以下是一个简单的animateTo使用示例:
@Entry
@Component
struct AnimateToExample {
@State widthSize: number = 250
@State heightSize: number = 100
@State rotateAngle: number = 0
private flag: boolean = true
build() {
Column() {
Button('change size').width(this.widthSize).height(this.heightSize).margin(30).onClick(() => {
if (this.flag) {
animateTo({
duration: 2000,
curve: Curve.EaseOut,
iterations: 3,
playMode: PlayMode.Normal,
onFinish: () => {
console.info('play end')
}
}, () => {
this.widthSize = 150
this.heightSize = 60
})
} else {
animateTo({}, () => {
this.widthSize = 250
this.heightSize = 100
})
}
this.flag = !this.flag
})
Button('stop rotating')
.margin(50)
.rotate({
x: 0,
y: 0,
z: 1,
angle: this.rotateAngle
})
.onAppear(() => {
// 组件出现时开始做动画
animateTo({
duration: 1200,
curve: Curve.Friction,
delay: 500,
iterations: -1,
// 设置-1表示动画无限循环
playMode: PlayMode.Alternate,
expectedFrameRateRange: { min: 10, max: 120, expected: 60, }
}, () => {
this.rotateAngle = 90
})
}).onClick(() => {
animateTo({ duration: 0 },
() => {
// this.rotateAngle之前为90,在duration为0的动画中修改属性,可以停止该属性之前的动画,按新设置的属性显示
this.rotateAngle = 0
})
})
}.width('100%').margin({ top: 5 })
}
}
组件消失动画示例
animateTo也可以用于实现组件消失时的动画效果:
@Entry
@Component
struct AttrAnimationExample {
@State heightSize: number = 100;
@State isShow: boolean = true;
@State count: number = 0;
private isToBottom: boolean =
true;
// 向下
build() {
Column() {
if (this.isShow) {
Column().width(200).height(this.heightSize).backgroundColor('blue').onClick(() => {
animateTo({
duration: 2000,
curve: Curve.EaseOut,
iterations: 1,
playMode: PlayMode.Normal,
onFinish: () => {
this.count--;
if (this.count == 0 &&
!this.isToBottom) {
// 组件只有在向下做完动画才会消失
this.isShow = false;
}
}
}, () => {
this.count++;
if (this.isToBottom) {
this.heightSize = 60;
} else {
this.heightSize = 100;
}
this.isToBottom = !this.isToBottom;
})
})
}
}.width('100%').height('100%').margin({ top: 5 }).justifyContent(FlexAlign.End)
}
}
官网给的效果图是这样的
但我自己实验后发现并没有回弹的这个效果,
实验设备为
HUAWEI Mate 60 Pro
OpenHarmony 5.0.1.120 (API 17)
动画曲线
animateTo支持多种动画曲线,可以通过curve参数指定:
import { curves } from '@kit.ArkUI';
@Entry
@Component
struct AnimateToDemo {
@State animate: boolean = false;
@State rotateValue: number = 0;
@State translateX: number = 0;
@State opacityValue: number = 1;
build() {
Row() {
Column() {
}
.rotate({ angle: this.rotateValue })
.backgroundColor('#317AF7')
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.borderRadius(30)
.onClick(() => {
this.getUIContext()?.animateTo({ curve: curves.springMotion() }, () => {
this.animate = !this.animate;
this.rotateValue = this.animate ? 90 : 0;
this.opacityValue = this.animate ? 0.6 : 1;
this.translateX = this.animate ? 50 : 0;
})
})
Column() {
}
.justifyContent(FlexAlign.Center)
.width(100)
.height(100)
.backgroundColor('#D94838')
.borderRadius(30)
.opacity(this.opacityValue)
.translate({ x: this.translateX })
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
性能优化
为了优化动画性能,animateTo提供了一些高级参数:
animateTo({ expectedFrameRateRange: { min: 10, max: 120, expected: 60, } }, () => { // 动画代码 })
状态管理V2中的注意事项
在状态管理V2中使用animateTo时需要注意一些特殊情况:
@Entry
@ComponentV2
struct Index {
@Local w: number = 50;
@Local h: number = 50;
@Local message: string = 'Hello';
build() {
Column() {
Button('change size').margin(20).onClick(() => {
this.w = 100;
this.h = 100;
this.message = 'Hello World';
animateTo({ duration: 1000 }, () => {
this.w = 200;
this.h = 200;
this.message = 'Hello ArkUI';
})
})
Column() {
Text(`${this.message}`)
}.backgroundColor('#ff17a98d').width(this.w).height(this.h)
}
}
}
可以通过以下方式获得预期效果:
@Entry
@ComponentV2
struct Index {
@Local w: number = 50;
@Local h: number = 50;
@Local message: string = 'Hello';
build() {
Column() {
Button('change size').margin(20).onClick(() => {
this.w = 100;
this.h = 100;
this.message = 'Hello Word';
animateToImmediately({ duration: 0 }, () => {
})
animateTo({ duration: 1000 }, () => {
this.w = 200;
this.h = 200;
this.message = 'Hello ArkUI';
})
})
Column() {
Text(`${this.message}`)
}.backgroundColor('#ff17a98d').width(this.w).height(this.h)
}
}
}
动画衔接
animateTo支持动画与动画、手势与动画之间的自然过渡:
import { curves } from '@kit.ArkUI';
class SetSlt {
isAnimation: boolean = true
set(): void {
this.isAnimation = !this.isAnimation;
}
}
@Entry
@Component
struct AnimationToAnimationDemo {
@State SetAnimation: SetSlt = new SetSlt();
build() {
Column() {
Text('ArkUI')
.fontWeight(FontWeight.Bold)
.fontSize(12)
.fontColor(Color.White)
.textAlign(TextAlign.Center)
.borderRadius(10)
.backgroundColor(0xf56c6c)
.width(100)
.height(100)
.scale({ x: this.SetAnimation.isAnimation ? 2 : 1, y: this.SetAnimation.isAnimation ? 2 : 1 })
.animation({ curve: curves.springMotion(0.4, 0.8) })
Button('Click').margin({ top: 200 }).onClick(() => {
this.SetAnimation.set()
})
}.width('100%').height('100%').justifyContent(FlexAlign.Center)
}
}
显式立即动画(animateToImmediately)
animateToImmediately是animateTo的变体,可以立即执行闭包代码中状态变化导致的过渡动效:
@Entry
@Component
struct AnimateToImmediatelyExample {
@State widthSize: number = 250
@State heightSize: number = 100
@State opacitySize: number = 0
private flag: boolean = true
build() {
Column() {
Column().width(this.widthSize).height(this.heightSize).backgroundColor(Color.Green).opacity(this.opacitySize)
Button('change size').margin(30).onClick(() => {
if (this.flag) {
animateToImmediately({ delay: 0, duration: 1000 }, () => {
this.opacitySize = 1
})
animateTo({ delay: 1000, duration: 1000 }, () => {
this.widthSize = 150
this.heightSize = 60
})
} else {
animateToImmediately({ delay: 0, duration: 1000 }, () => {
this.widthSize = 250
this.heightSize = 100
})
animateTo({ delay: 1000, duration: 1000 }, () => {
this.opacitySize = 0
})
}
this.flag = !this.flag
})
}.width('100%').margin({ top: 5 })
}
}
总结
animateTo是ArkUI中功能强大的显式动画接口,它通过对比闭包执行前后的状态差异来自动生成过渡动画。开发者可以通过配置动画参数、曲线类型等实现各种复杂的动画效果。同时,animateTo支持嵌套调用、动画衔接等高级特性,能够满足大多数UI动画需求。在使用时需要注意状态管理V2中的特殊情况,并合理使用animateToImmediately等变体来优化动画性能。
----
啰嗦一句:官网代码也不一定百分百正确,也可能是设备系统更新后官网示例没有更新。一切以实际为准
更多推荐
所有评论(0)