• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 属性动画接口说明
2
3
4通过可动画属性改变引起UI上产生的连续视觉效果,即为属性动画。属性动画是最基础易懂的动画,ArkUI提供两种属性动画接口[animateTo](../reference/arkui-ts/ts-explicit-animation.md)和[animation](../reference/arkui-ts/ts-animatorproperty.md)驱动组件属性按照动画曲线等动画参数进行连续的变化,产生属性动画。
5
6
7| 属性动画接口 | 作用域 | 原理 | 使用场景 |
8| -------- | -------- | -------- | -------- |
9| animateTo | 闭包内改变属性引起的界面变化。<br/>作用于出现消失转场。 | 通用函数,对闭包前界面和闭包中的状态变量引起的界面之间的差异做动画。<br/>支持多次调用,支持嵌套。 | 适用对多个可动画属性配置相同动画参数的动画。<br/>需要嵌套使用动画的场景。 |
10| animation | 组件通过属性接口绑定的属性变化引起的界面变化。 | 识别组件的可动画属性变化,自动添加动画。<br/>组件的接口调用是从下往上执行,animation只会作用于在其之上的属性调用。<br/>组件可以根据调用顺序对多个属性设置不同的animation。 | 适用于对多个可动画属性配置不同参数动画的场景。 |
11
12
13## 使用animateTo产生属性动画
14
15
16```
17animateTo(value: AnimateParam, event: () => void): void
18```
19
20[animateTo](../reference/arkui-ts/ts-explicit-animation.md)接口参数中,value指定[动画参数](../reference/arkui-ts/ts-explicit-animation.md#animateparam对象说明)(包括时长、[曲线](../reference/apis/js-apis-curve.md#curve)等)event为动画的闭包函数,闭包内变量改变产生的属性动画将遵循相同的动画参数。
21
22
23```ts
24import curves from '@ohos.curves'
25
26@Entry
27@Component
28struct AnimateToDemo {
29  @State animate: boolean = false;
30  // 第一步: 声明相关状态变量
31  @State rotateValue: number = 0; // 组件一旋转角度
32  @State translateY: number = 0; // 组件二偏移量
33  @State opacityValue: number = 1; // 组件二透明度
34
35  // 第二步:将状态变量设置到相关可动画属性接口
36  build() {
37    Column() {
38      // 组件一
39      Column() {
40        Text('ArkUI')
41          .fontWeight(FontWeight.Bold)
42          .fontSize(20)
43          .fontColor(Color.White)
44      }
45      .justifyContent(FlexAlign.Center)
46      .width(150)
47      .height(150)
48      .borderRadius(10)
49      .rotate({ angle: this.rotateValue })
50      .backgroundColor(0xf56c6c)
51
52      // 组件二
53      Column() {
54        Text('ArkUI')
55          .fontWeight(FontWeight.Bold)
56          .fontSize(20)
57          .fontColor(Color.White)
58      }
59      .justifyContent(FlexAlign.Center)
60      .width(150)
61      .height(150)
62      .backgroundColor(0x67C23A)
63      .borderRadius(10)
64      .opacity(this.opacityValue)
65      .translate({ y: this.translateY })
66
67      Button('Click')
68        .margin({ top: 120 })
69        .onClick(() => {
70          this.animate = !this.animate;
71          // 第三步:通过属性动画接口开启属性动画
72          animateTo({ curve: curves.springMotion() }, () => {
73            // 第四步:闭包内通过状态变量改变UI界面
74            // 这里可以写任何能改变UI的逻辑比如数组添加,显隐控制,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画
75            // 组件一的rotate属性发生变化,所以会给组件一添加rotate旋转动画
76            this.rotateValue = this.animate ? 90 : 0;
77            // 组件二的scale属性发生变化,所以会给组件二添加scale缩放动画
78            this.opacityValue = this.animate ? 0.6 : 1;
79            // 组件二的offset属性发生变化,所以会给组件二添加offset偏移动画
80            this.translateY = this.animate ? 100 : 0;
81          })
82        })
83    }
84    .width('100%')
85    .height('100%')
86    .justifyContent(FlexAlign.Center)
87  }
88}
89```
90
91![zh-cn_image_0000001599958466](figures/zh-cn_image_0000001599958466.gif)
92
93
94## 使用animation产生属性动画
95
96相比于animateTo接口需要把要执行动画的属性的修改放在闭包中,[animation](../reference/arkui-ts/ts-animatorproperty.md)接口无需使用闭包,把animation接口加在要做属性动画的可动画属性后即可。animation只要检测到其绑定的可动画属性发生变化,就会自动添加属性动画,animateTo则必须在动画闭包内改变可动画属性的值从而生成动画。
97
98
99```ts
100import curves from '@ohos.curves';
101
102@Entry
103@Component
104struct AnimationDemo {
105  @State animate: boolean = false;
106  // 第一步: 声明相关状态变量
107  @State rotateValue: number = 0; // 组件一旋转角度
108  @State translateY: number = 0; // 组件二偏移量
109  @State color: Color = Color.White; // 组件二字体颜色
110  @State opacityValue: number = 1; // 父组件透明度
111
112  // 第二步:将状态变量设置到相关可动画属性接口
113  build() {
114    Column() {
115      Column() {
116        // 组件一
117        Text('ArkUI')
118          .fontWeight(FontWeight.Bold)
119          .fontSize(20)
120          .fontColor(Color.White)
121          .textAlign(TextAlign.Center)
122          .borderRadius(10)
123          .backgroundColor(0xf56c6c)
124          .rotate({ angle: this.rotateValue })
125            // 第三步:通过属性动画接口开启属性动画,控件的函数调用顺序是从下往上的,这个animation会作用到上面的rotate属性
126          .animation({ curve: curves.springMotion(0.3, 1.0) })
127          .width(150)
128          .height(150)
129
130        // 组件二
131        Text('ArkUI')
132          .fontWeight(FontWeight.Bold)
133          .fontSize(20)
134          .fontColor(this.color)
135            // 第三步:通过属性动画接口开启属性动画,控件的函数调用顺序是从下往上的,这个animation会作用到上面的fontColor属性
136          .animation({ curve: curves.springMotion(0.6, 1.2) })
137          .textAlign(TextAlign.Center)
138          .borderRadius(10)
139          .backgroundColor(0x67C23A)
140          .width(150)
141          .height(150)
142          .translate({ y: this.translateY })
143            // 第三步:通过属性动画接口开启属性动画,控件的函数调用顺序是从下往上的,这个animation会作用到上面的translate属性
144          .animation({ curve: curves.springMotion(0.3, 0.6) })
145      }
146      .justifyContent(FlexAlign.Center)
147      .opacity(this.opacityValue)
148      // 这个animation会作用到上面的opacity属性,父组件column的透明度变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画
149      .animation({ curve: curves.springMotion() })
150
151      // 第四步:通过状态变量改变UI界面,系统会检测改变后的UI界面与之前的UI界面的差异,对有差异的部分添加动画
152      Button('Click')
153        .margin({ top: 120 })
154        .onClick(() => {
155          this.animate = !this.animate;
156          // 组件一的rotate属性有变化,所以会给组件一加rotate动画
157          this.rotateValue = this.animate ? 90 : 0;
158          // 组件二的translate属性有变化,所以会给组件二加translate动画
159          this.translateY = this.animate ? 100 : 0;
160          // 组件二的fontColor属性有变化,所以会给组件二加fontColor动画
161          this.color = this.animate ? Color.Black : Color.White;
162          // 父组件column的opacity属性有变化,会导致其子节点的透明度也变化,所以这里会给column和其子节点的透明度属性都加动画
163          this.opacityValue = this.animate ? 0.6 : 1;
164        })
165
166    }
167    .width('100%')
168    .height('100%')
169    .justifyContent(FlexAlign.Center)
170  }
171}
172```
173
174![zh-cn_image_0000001649279705](figures/zh-cn_image_0000001649279705.gif)
175
176> **说明:**
177> - 在对组件的位置大小的变化做动画的时候,由于布局属性的改变会触发测量布局,性能开销大。[scale](../reference/arkui-ts/ts-universal-attributes-transformation.md)属性的改变不会触发测量布局,性能开销小。因此,在组件位置大小持续发生变化的场景,如跟手触发组件大小变化的场景,推荐适用scale。
178>
179> - 属性动画应该作用于始终存在的组件,对于将要出现或者将要消失的组件的动画应该使用[转场动画](arkts-transition-overview.md)。
180>
181> - 尽量不要使用动画结束回调。属性动画是对已经发生的状态进行的动画,不需要开发者去处理结束的逻辑。如果要使用结束回调,一定要正确处理连续操作的数据管理。
182