一、定义
当组件的通用属性发生改变时而产生的属性渐变效果
说明:
当组件的通用属性发生改变时,组件状态由初始状态逐渐变为结束状态的过程中,会创建多个连续的中间状态,逐帧播放后,就会形成动画
二、创建
给组件(如lmage、Button、 Column等)添加animation属性,并设置属性动画的参数
参数:
- duration:动画时长,单位为毫秒,默认时长为1000毫秒
- tempo:动画的播放速度,值越大动画播放越快,值越小播放越慢,为0时无动画效果,默认值:1
- curve:动画变化曲线,默认曲线为线性,默认值是:Curve.Linear
名称 | 描述 |
---|---|
Linear | 表示动画从头到尾的速度都是相同的。 |
Ease | 表示动画以低速开始,然后加快,在结束前变慢,CubicBezier(0.25, 0.1, 0.25, 1.0)。 |
EaseIn | 表示动画以低速开始,CubicBezier(0.42, 0.0, 1.0, 1.0)。 |
EaseOut | 表示动画以低速结束,CubicBezier(0.0, 0.0, 0.58, 1.0)。 |
EaseInOut | 表示动画以低速开始和结束,CubicBezier(0.42, 0.0, 0.58, 1.0)。 |
FastOutSlowIn | 标准曲线,cubic-bezier(0.4, 0.0, 0.2, 1.0)。 |
LinearOutSlowIn | 减速曲线,cubic-bezier(0.0, 0.0, 0.2, 1.0)。 |
FastOutLinearIn | 加速曲线,cubic-bezier(0.4, 0.0, 1.0, 1.0)。 |
ExtremeDeceleration | 急缓曲线,cubic-bezier(0.0, 0.0, 0.0, 1.0)。 |
Sharp | 锐利曲线,cubic-bezier(0.33, 0.0, 0.67, 1.0)。 |
Rhythm | 节奏曲线,cubic-bezier(0.7, 0.0, 0.2, 1.0)。 |
Smooth | 平滑曲线,cubic-bezier(0.4, 0.0, 0.4, 1.0)。 |
Friction | 阻尼曲线,CubicBezier(0.2, 0.0, 0.2, 1.0)。 |
- delay:延时播放时间,单位为毫秒,默认值:0,不延时播放
- iterations:播放次数,默认值:1,设置为-1时表示无限次播放
- playMode:设置动画播放模式,默认:播放完成后重头开始播放
名称 | 描述 |
---|---|
Normal | 动画按正常播放 |
Reverse | 动画反向播放 |
Alternate | 动画在奇数次(1、3、5...)正向播放,在偶数次(2、4、6...)反向播放 |
AlternateReverse | 动画在奇数次(1、3、5...)反向播放,在偶数次(2、4、6...)正向播放 |
- onFinish:动画播放结束时回调
三、使用:
Image($r('app.media._icon')) .animation({ duration: 1000, tempo: 1.0, delay: 0, curve: Curve.Linear, playMode: PlayMode.Normal, iterations: 1 })
发现动画并未执行,原因可能如下:
- 产生属性动画的属性需要在animation之前声明
- 产生属性动画的属性变化时需触发UI状态更新
- 产生属性动画的属性本身需满足一定的要求,并非任何属性都可以产生属性动画。目前支持的属性包括width、height、position、opacity、backgroundColor、scale、rotate、translate等
三、案例
旋转动画 rotate
@Entry
@Component
struct AnimPage {@State rotateAngle: number = 0build() {Row() {Column() {Button("开启旋转动画", { type: ButtonType.Capsule, stateEffect: true }).onClick(() => {this.rotateAngle = 360})Row({ space: 20 }) {//沿着X轴旋转Image($r('app.media.app_icon')).width(80).height(80).rotate({ x: 1, y: 0, z: 0, angle: this.rotateAngle }).animation({duration: 2000,tempo: 1.0,delay: 0,curve: Curve.Linear,playMode: PlayMode.Normal,iterations: -1})//沿着Y轴旋转Image($r('app.media.app_icon')).width(80).height(80).rotate({ x: 0, y: 1, z: 0, angle: this.rotateAngle }).animation({duration: 2000,tempo: 1.0,delay: 0,curve: Curve.Linear,playMode: PlayMode.Normal,iterations: -1})//沿着Z轴旋转Image($r('app.media.app_icon')).width(80).height(80).rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle }).animation({duration: 2000,tempo: 1.0,delay: 0,curve: Curve.Linear,playMode: PlayMode.Normal,iterations: -1})Image($r('app.media.app_icon')).width(80).height(80).rotate({ x: 0, y: 0, z: 1, angle: this.rotateAngle }).animation({duration: 2000,tempo: 1.0,delay: 0,//低速开始,然后加快,在结束前变慢curve: Curve.Ease,//playMode: PlayMode.Reverse,iterations: -1})}.margin({ top: 20 }).padding({ left: 10 }).height("30%").width("100%").backgroundColor(Color.Red)}.width('100%')}.height('100%')}
}
位移动画 position
@Entry
@Component
struct AnimPage {@State xState: number = 0@State yState: number = 0build() {Row() {Column() {Row() {Text('位移动画').width(200).height(100).fontColor(Color.Blue).fontSize(30).margin(100).position({ x: this.xState, y: 0 }).animation({duration: 1000,tempo: 1.0,delay: 0,curve: Curve.Linear,playMode: PlayMode.Normal,iterations: 1,onFinish: () => {this.xState = 200}})Image($r('app.media.app_icon')).width(80).height(80).position({ x: 0, y: this.yState }).animation({duration: 1000,tempo: 1.0,delay: 0,curve: Curve.Linear,playMode: PlayMode.Normal,iterations: 1,onFinish: () => {//在onFinish回调中重新设置了xState和yState,也可以实现永久播放的效果if (this.yState == 0) {this.yState = 200} else {this.yState = 0}}})}.height("30%").width("100%").backgroundColor(Color.Red)}.width('100%')}.height('100%')}
}
缩放动画 width、height
@Entry
@Component
struct AnimPage {@State widthSize: number = 250@State heightSize: number = 100@State flag: boolean = truebuild() {Row() {Column() {Button('缩放').onClick(() => {if (this.flag) {this.widthSize = 150this.heightSize = 60} else {this.widthSize = 250this.heightSize = 100}this.flag = !this.flag}).margin(30).width(this.widthSize).height(this.heightSize).animation({duration: 2000,curve: Curve.EaseOut,iterations: 3,playMode: PlayMode.Normal})}.width('100%').height('30%').backgroundColor(Color.Red)}.width('100%').height('100%')}
}
透明度动画 opacity
@Entry
@Component
struct AnimPage {@State opacityAngle: number = 1build() {Row() {Column() {Button('透明度').onClick(() => {this.opacityAngle = 0}).margin(50).opacity(this.opacityAngle).animation({duration: 2000,curve: Curve.Friction,delay: 500,iterations: -1, // 设置-1表示动画无限循环playMode: PlayMode.Alternate})}.width('100%').height('30%').backgroundColor(Color.Red)}.width('100%').height('100%')}
}