• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 帧动画
2
3通过返回应用onFrame逐帧回调的方式,让开发者在应用侧的每一帧都可以设置属性值,从而实现设置了该属性值对应组件的动画效果。接口的详细介绍请查看[@ohos.animator (动画)](../reference/apis-arkui/js-apis-animator.md)。
4
5相比于属性动画,开发者可感知动画的过程,实时修改UI侧的值,具有事件可实时响应、可暂停的优点,但性能上不如属性动画。在属性动画符合要求时更推荐使用属性动画的接口实现,可参照[实现属性动画](./arkts-attribute-animation-apis.md)。
6
7
8## 使用animator实现动画效果
9
10使用如下步骤可以创建一个简单的animator,并且在每个帧回调中打印当前插值。
11
121. 引入相关依赖。
13
14   ```ts
15   import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
16   ```
17
182. 创建执行动画的对象。
19
20   ```ts
21   // 创建动画的初始参数
22   let options: AnimatorOptions = {
23      duration: 1500,
24      easing: "friction",
25      delay: 0,
26      fill: "forwards",
27      direction: "normal",
28      iterations: 2,
29      // 动画onFrame 插值首帧值
30      begin: 200.0,
31      // 动画onFrame 插值尾帧值
32      end: 400.0
33   };
34   let result: AnimatorResult = this.getUIContext().createAnimator(options);
35      // 设置接收到帧时回调,动画播放过程中每帧会调用onFrame回调
36       result.onFrame = (value: number) => {
37       console.log("current value is :" + value);
38   }
39   ```
40
413. 播放动画。
42
43   ```ts
44   // 播放动画
45   result.play();
46   ```
47
484. 动画执行完成后手动释放AnimatorResult对象。
49
50   ```ts
51   // 释放动画对象
52   result = undefined;
53   ```
54
55## 使用animator实现小球抛物运动
56
571. 引入相关依赖。
58
59   ```ts
60   import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
61   ```
62
632. 定义要做动画的组件。
64
65   ```ts
66   Button()
67     .width(60)
68     .height(60)
69     .translate({ x: this.translateX, y: this.translateY })
70   ```
71
723. 在onPageShow中创建AnimatorResult对象。
73
74   ```ts
75   onPageShow(): void {
76       //创建animatorResult对象
77       this.animatorOptions = this.getUIContext().createAnimator(options);
78       this.animatorOptions.onFrame = (progress: number) => {
79       this.translateX = progress;
80       if (progress > this.topWidth && this.translateY < this.bottomHeight) {
81          this.translateY = Math.pow(progress - this.topWidth, 2) * this.g;
82       }
83    }
84    //动画取消时执行方法
85    this.animatorOptions.onCancel = () => {
86       this.animatorStatus = '取消';
87    }
88    //动画完成时执行方法
89    this.animatorOptions.onFinish = () => {
90       this.animatorStatus = '完成';
91    }
92    //动画重复播放时执行方法
93    this.animatorOptions.onRepeat = () => {
94       console.log("动画重复播放");
95    }
96   }
97   ```
98
994. 定义动画播放,重置,暂停的按钮。
100
101   ```ts
102   Button('播放').onClick(() => {
103     this.animatorOptions?.play();
104     this.animatorStatus = '播放中'
105   }).width(80).height(35)
106   Button("重置").onClick(() => {
107     this.translateX = 0;
108     this.translateY = 0;
109   }).width(80).height(35)
110   Button("暂停").onClick(() => {
111     this.animatorOptions?.pause();
112     this.animatorStatus = '暂停'
113   }).width(80).height(35)
114   ```
1155. 在页面隐藏或销毁的生命周期中释放动画对象,避免内存泄漏。
116   ```ts
117   onPageHide(): void {
118     this.animatorOptions = undefined;
119   }
120   ```
121
122完整示例如下。
123
124```ts
125import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
126
127@Entry
128@Component
129struct Index {
130  @State animatorOptions: AnimatorResult | undefined = undefined;
131  @State animatorStatus: string = '创建';
132  begin: number = 0;
133  end: number = 300
134  topWidth: number = 150;
135  bottomHeight: number = 100;
136  g: number = 0.18
137  animatorOption: AnimatorOptions = {
138    duration: 4000,
139    delay: 0,
140    easing: 'linear',
141    iterations: 1,
142    fill: "forwards",
143    direction: 'normal',
144    begin: this.begin,
145    end: this.end
146  };
147  @State translateX: number = 0;
148  @State translateY: number = 0;
149
150  onPageShow(): void {
151    this.animatorOptions = this.getUIContext().createAnimator(this.animatorOption)
152    this.animatorOptions.onFrame = (progress: number) => {
153      this.translateX = progress;
154      if (progress > this.topWidth && this.translateY < this.bottomHeight) {
155        this.translateY = Math.pow(progress - this.topWidth, 2) * this.g;
156      }
157    }
158    this.animatorOptions.onCancel = () => {
159      this.animatorStatus = '取消';
160    }
161    this.animatorOptions.onFinish = () => {
162      this.animatorStatus = '完成';
163    }
164    this.animatorOptions.onRepeat = () => {
165      console.log("动画重复播放");
166    }
167  }
168
169  onPageHide(): void {
170    this.animatorOptions = undefined;
171  }
172
173  build() {
174    Column() {
175      Column({ space: 30 }) {
176        Button('播放').onClick(() => {
177          this.animatorOptions?.play();
178          this.animatorStatus = '播放中';
179        }).width(80).height(35)
180        Button("重置").onClick(() => {
181          this.translateX = 0;
182          this.translateY = 0;
183        }).width(80).height(35)
184        Button("暂停").onClick(() => {
185          this.animatorOptions?.pause();
186          this.animatorStatus = '暂停';
187        }).width(80).height(35)
188      }.width("100%").height('25%')
189
190      Stack() {
191        Button()
192          .width(60)
193          .height(60)
194          .translate({ x: this.translateX, y: this.translateY })
195      }
196      .width("100%")
197      .height('45%')
198      .align(Alignment.Start)
199
200      Text("当前动画状态为:" + this.animatorStatus)
201    }.width("100%").height('100%')
202  }
203}
204```
205
206![zh-cn_image_0000001599958466](figures/animatorSimple.gif)