• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 使用属性动画替换帧动画
2
3帧动画具备逐帧回调的特性,便于开发者在每一帧中处理需调整的属性。通过向应用提供onFrame逐帧回调,帧动画使开发者能够在应用的每一帧设置属性值,从而实现组件属性值变化的自然过渡,营造出动画效果。帧动画接口详情可参考[@ohos.animator (动画)](../reference/apis-arkui/js-apis-animator.md)。
4
5与属性动画相比,帧动画能让开发者实时感知动画进程,即时调整UI值,具备事件即时响应和可暂停的优势,但在性能上略逊于属性动画。当属性动画能满足需求时,建议优先采用属性动画接口实现。属性动画接口可参考[实现属性动画](../ui/arkts-attribute-animation-apis.md)。
6
7本文对比了属性动画和帧动画实现相同动效在性能上的差异。
8
9**反例:**
10
11```ts
12import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
13
14@Entry
15@Component
16struct Index {
17  @State animatorOptions: AnimatorResult | undefined = undefined;
18  @State animatorStatus: string = '创建';
19  begin: number = 0;
20  end: number = 100;
21  @State widthSize: number = 100;
22  @State heightSize: number = 50;
23  animatorOption: AnimatorOptions = {
24    duration: 2000,
25    delay: 0,
26    easing: 'linear',
27    iterations: 1,
28    fill: "forwards",
29    direction: 'normal',
30    begin: this.begin,
31    end: this.end
32  };
33
34  onPageShow(): void {
35    this.animatorOptions = this.getUIContext().createAnimator(this.animatorOption)
36    this.animatorOptions.onFrame = (progress: number) => {
37      this.widthSize = 100 + progress
38      this.heightSize = 50 + progress/2
39    }
40  }
41
42  onPageHide(): void {
43    this.animatorOptions = undefined;
44  }
45
46  build() {
47    Column() {
48      Column({ space: 30 }) {
49        Button('播放').onClick(() => {
50          this.animatorOptions?.play();
51          this.animatorStatus = '播放中';
52        }).width(80).height(35)
53      }.width("100%").height('25%')
54
55      Stack() {
56        Button()
57          .width(this.widthSize).height(this.heightSize)
58      }
59      .width("100%")
60      .height('45%')
61      .align(Alignment.Start)
62
63      Text("当前动画状态为:" + this.animatorStatus)
64    }.width("100%").height('100%')
65  }
66}
67```
68
69**正例:**
70
71```ts
72@Entry
73@Component
74struct AttrAnimationExample1 {
75  @State widthSize: number = 200;
76  @State heightSize: number = 100;
77  @State flag: boolean = true;
78
79  build() {
80    Column() {
81      Button('click me')
82        .onClick((event?: ClickEvent | undefined) => {
83          if (this.flag) {
84            this.widthSize = 100;
85            this.heightSize = 50;
86          } else {
87            this.widthSize = 200;
88            this.heightSize = 100;
89          }
90          this.flag = !this.flag;
91        })
92        .width(this.widthSize).height(this.heightSize).backgroundColor(0x317aff)
93        .animation({
94          duration: 2000, // 动画时长
95          curve: Curve.Linear, // 动画曲线
96          delay: 0, // 动画延迟
97          iterations: 1, // 播放次数
98          playMode: PlayMode.Normal // 动画模式
99        }) // 对Button组件的宽高属性进行动画配置
100    }.width('100%').margin({ top: 5 })
101  }
102}
103```
104
105更详细的API文档请参考:[属性动画](../reference/apis-arkui/arkui-ts/ts-animatorproperty.md)。
106
107## 优化效果
108
109| 属性动画                                         | 帧动画                                          |
110|----------------------------------------------------|----------------------------------------------------|
111| ![img](./figures/using-animation-instaeadof-animator-animation.png) | ![img](./figures/using-animation-instaeadof-animator-animator.png) |
112
113上述示例通过使用属性动画将UI应用主线程的负载降为0。