1e41f4b71Sopenharmony_ci# Frame Animation
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ciFrame animation involves the use of the **onFrame** callback in applications, which allows you to adjust property values with each frame that is rendered, thereby creating animation effects for the components associated with those property values. For details about the APIs, see [@ohos.animator (Animator)](../reference/apis-arkui/js-apis-animator.md).
4e41f4b71Sopenharmony_ci
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ci## Implementing an Animation with animator
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciTo create a simple animator and print the current interpolation value in each frame callback:
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci1. Import dependencies.
11e41f4b71Sopenharmony_ci
12e41f4b71Sopenharmony_ci   ```ts
13e41f4b71Sopenharmony_ci   import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
14e41f4b71Sopenharmony_ci   ```
15e41f4b71Sopenharmony_ci
16e41f4b71Sopenharmony_ci2. Create an animator object.
17e41f4b71Sopenharmony_ci
18e41f4b71Sopenharmony_ci   ```ts
19e41f4b71Sopenharmony_ci   // Initial options for creating an animator object
20e41f4b71Sopenharmony_ci   let options: AnimatorOptions = {                        
21e41f4b71Sopenharmony_ci      duration: 1500,                               
22e41f4b71Sopenharmony_ci      easing: "friction",                        
23e41f4b71Sopenharmony_ci      delay: 0,                           
24e41f4b71Sopenharmony_ci      fill: "forwards",                                  
25e41f4b71Sopenharmony_ci      direction: "normal",                                  
26e41f4b71Sopenharmony_ci      iterations: 2,                                        
27e41f4b71Sopenharmony_ci      // Initial frame value used for interpolation in the onFrame callback                                   
28e41f4b71Sopenharmony_ci      begin: 200.0,                                         
29e41f4b71Sopenharmony_ci      // End frame value used for interpolation in the onFrame callback                                   
30e41f4b71Sopenharmony_ci      end: 400.0                                            
31e41f4b71Sopenharmony_ci   }; 
32e41f4b71Sopenharmony_ci   let result: AnimatorResult = this.getUIContext().createAnimator(options);
33e41f4b71Sopenharmony_ci      // Set up a callback for when a frame is received, so that the onFrame callback is called for every frame throughout the animation playback process.
34e41f4b71Sopenharmony_ci       result.onFrame = (value: number) => {
35e41f4b71Sopenharmony_ci       console.log("current value is :" + value);
36e41f4b71Sopenharmony_ci   }
37e41f4b71Sopenharmony_ci   ```
38e41f4b71Sopenharmony_ci
39e41f4b71Sopenharmony_ci3. Play the animation.
40e41f4b71Sopenharmony_ci
41e41f4b71Sopenharmony_ci   ```ts
42e41f4b71Sopenharmony_ci   // Play the animation.
43e41f4b71Sopenharmony_ci   result.play();
44e41f4b71Sopenharmony_ci   ```
45e41f4b71Sopenharmony_ci
46e41f4b71Sopenharmony_ci4. After the animation has finished executing, manually release the **AnimatorResult** object.
47e41f4b71Sopenharmony_ci
48e41f4b71Sopenharmony_ci   ```ts
49e41f4b71Sopenharmony_ci   // Play the animation.
50e41f4b71Sopenharmony_ci   result = undefined;
51e41f4b71Sopenharmony_ci   ```
52e41f4b71Sopenharmony_ci
53e41f4b71Sopenharmony_ci## Implementing a Ball's Parabolic Motion with Animator
54e41f4b71Sopenharmony_ci
55e41f4b71Sopenharmony_ci1. Import dependencies.
56e41f4b71Sopenharmony_ci
57e41f4b71Sopenharmony_ci   ```ts
58e41f4b71Sopenharmony_ci   import { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
59e41f4b71Sopenharmony_ci   ```
60e41f4b71Sopenharmony_ci
61e41f4b71Sopenharmony_ci2. Define the component to be animated.
62e41f4b71Sopenharmony_ci
63e41f4b71Sopenharmony_ci   ```ts
64e41f4b71Sopenharmony_ci   Button()
65e41f4b71Sopenharmony_ci     .width(60)
66e41f4b71Sopenharmony_ci     .height(60)
67e41f4b71Sopenharmony_ci     .translate({ x: this.translateX, y: this.translateY })
68e41f4b71Sopenharmony_ci   ```
69e41f4b71Sopenharmony_ci
70e41f4b71Sopenharmony_ci3. Create an **AnimatorResult** Object in **onPageShow**.
71e41f4b71Sopenharmony_ci
72e41f4b71Sopenharmony_ci   ```ts
73e41f4b71Sopenharmony_ci   onPageShow(): void {
74e41f4b71Sopenharmony_ci       // Create an animatorResult object.
75e41f4b71Sopenharmony_ci       this.animatorOptions = this.getUIContext().createAnimator(options);
76e41f4b71Sopenharmony_ci       this.animatorOptions.onFrame = (progress: number) => {
77e41f4b71Sopenharmony_ci       this.translateX = progress;
78e41f4b71Sopenharmony_ci       if (progress > this.topWidth && this.translateY < this.bottomHeight) {
79e41f4b71Sopenharmony_ci          this.translateY = Math.pow(progress - this.topWidth, 2) * this.g;
80e41f4b71Sopenharmony_ci       }
81e41f4b71Sopenharmony_ci    }
82e41f4b71Sopenharmony_ci    // Invoked when the animation is canceled.
83e41f4b71Sopenharmony_ci    this.animatorOptions.onCancel = () => {
84e41f4b71Sopenharmony_ci       this.animatorStatus = 'Canceled'
85e41f4b71Sopenharmony_ci    }
86e41f4b71Sopenharmony_ci    // Invoked when the animation finishes playing.
87e41f4b71Sopenharmony_ci    this.animatorOptions.onFinish = () => {
88e41f4b71Sopenharmony_ci       this.animatorStatus = 'Finished'
89e41f4b71Sopenharmony_ci    }
90e41f4b71Sopenharmony_ci    // Invoked when the animation repeats.
91e41f4b71Sopenharmony_ci    this.animatorOptions.onRepeat = () => {
92e41f4b71Sopenharmony_ci       console.log("Animation repeating");
93e41f4b71Sopenharmony_ci    }
94e41f4b71Sopenharmony_ci   }
95e41f4b71Sopenharmony_ci   ```
96e41f4b71Sopenharmony_ci
97e41f4b71Sopenharmony_ci4. Define buttons for controlling the animation.
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci   ```ts
100e41f4b71Sopenharmony_ci   Button('Play').onClick(() => {
101e41f4b71Sopenharmony_ci     this.animatorOptions?.play();
102e41f4b71Sopenharmony_ci     this.animatorStatus = 'Playing'
103e41f4b71Sopenharmony_ci   }).width(80).height(35)
104e41f4b71Sopenharmony_ci   Button("Reset").onClick(() => {
105e41f4b71Sopenharmony_ci     this.translateX = 0;
106e41f4b71Sopenharmony_ci     this.translateY = 0;
107e41f4b71Sopenharmony_ci   }).width(80).height(35)
108e41f4b71Sopenharmony_ci   Button("Pause").onClick(() => {
109e41f4b71Sopenharmony_ci     this.animatorOptions?.pause();
110e41f4b71Sopenharmony_ci     this.animatorStatus = 'Paused'
111e41f4b71Sopenharmony_ci   }).width(80).height(35)
112e41f4b71Sopenharmony_ci   ```
113e41f4b71Sopenharmony_ci5. Destroy the animation in the page's **onPageHide** lifecycle callback.
114e41f4b71Sopenharmony_ci   ```ts
115e41f4b71Sopenharmony_ci   onPageHide(): void {
116e41f4b71Sopenharmony_ci     this.animatorOptions = undefined;
117e41f4b71Sopenharmony_ci   }
118e41f4b71Sopenharmony_ci   ```
119e41f4b71Sopenharmony_ci
120e41f4b71Sopenharmony_ciA complete example is as follows:
121e41f4b71Sopenharmony_ci
122e41f4b71Sopenharmony_ci```ts
123e41f4b71Sopenharmony_ciimport { AnimatorOptions, AnimatorResult } from '@kit.ArkUI';
124e41f4b71Sopenharmony_ci
125e41f4b71Sopenharmony_ci@Entry
126e41f4b71Sopenharmony_ci@Component
127e41f4b71Sopenharmony_cistruct Index {
128e41f4b71Sopenharmony_ci  @State animatorOptions: AnimatorResult | undefined = undefined;
129e41f4b71Sopenharmony_ci  @State animatorStatus: string =' Created'
130e41f4b71Sopenharmony_ci  begin: number = 0;
131e41f4b71Sopenharmony_ci  end: number = 300
132e41f4b71Sopenharmony_ci  topWidth: number = 150;
133e41f4b71Sopenharmony_ci  bottomHeight: number = 100;
134e41f4b71Sopenharmony_ci  g: number = 0.18
135e41f4b71Sopenharmony_ci  animatorOption: AnimatorOptions = {
136e41f4b71Sopenharmony_ci    duration: 4000,
137e41f4b71Sopenharmony_ci    delay: 0,
138e41f4b71Sopenharmony_ci    easing: 'linear',
139e41f4b71Sopenharmony_ci    iterations: 1,
140e41f4b71Sopenharmony_ci    fill: "forwards",
141e41f4b71Sopenharmony_ci    direction: 'normal',
142e41f4b71Sopenharmony_ci    begin: this.begin,
143e41f4b71Sopenharmony_ci    end: this.end
144e41f4b71Sopenharmony_ci  };
145e41f4b71Sopenharmony_ci  @State translateX: number = 0;
146e41f4b71Sopenharmony_ci  @State translateY: number = 0;
147e41f4b71Sopenharmony_ci
148e41f4b71Sopenharmony_ci  onPageShow(): void {
149e41f4b71Sopenharmony_ci    this.animatorOptions = this.getUIContext().createAnimator(this.animatorOption)
150e41f4b71Sopenharmony_ci    this.animatorOptions.onFrame = (progress: number) => {
151e41f4b71Sopenharmony_ci      this.translateX = progress;
152e41f4b71Sopenharmony_ci      if (progress > this.topWidth && this.translateY < this.bottomHeight) {
153e41f4b71Sopenharmony_ci        this.translateY = Math.pow(progress - this.topWidth, 2) * this.g;
154e41f4b71Sopenharmony_ci      }
155e41f4b71Sopenharmony_ci    }
156e41f4b71Sopenharmony_ci    this.animatorOptions.onCancel = () => {
157e41f4b71Sopenharmony_ci      this.animatorStatus = 'Canceled'
158e41f4b71Sopenharmony_ci    }
159e41f4b71Sopenharmony_ci    this.animatorOptions.onFinish = () => {
160e41f4b71Sopenharmony_ci      this.animatorStatus = 'Finished'
161e41f4b71Sopenharmony_ci    }
162e41f4b71Sopenharmony_ci    this.animatorOptions.onRepeat = () => {
163e41f4b71Sopenharmony_ci      console.log("Animation repeating");
164e41f4b71Sopenharmony_ci    }
165e41f4b71Sopenharmony_ci  }
166e41f4b71Sopenharmony_ci
167e41f4b71Sopenharmony_ci  onPageHide(): void {
168e41f4b71Sopenharmony_ci    this.animatorOptions = undefined;
169e41f4b71Sopenharmony_ci  }
170e41f4b71Sopenharmony_ci
171e41f4b71Sopenharmony_ci  build() {
172e41f4b71Sopenharmony_ci    Column() {
173e41f4b71Sopenharmony_ci      Column({ space: 30 }) {
174e41f4b71Sopenharmony_ci        Button('Play').onClick(() => {
175e41f4b71Sopenharmony_ci          this.animatorOptions?.play();
176e41f4b71Sopenharmony_ci          this.animatorStatus = 'Playing';
177e41f4b71Sopenharmony_ci        }).width(80).height(35)
178e41f4b71Sopenharmony_ci        Button("Reset").onClick(() => {
179e41f4b71Sopenharmony_ci          this.translateX = 0;
180e41f4b71Sopenharmony_ci          this.translateY = 0;
181e41f4b71Sopenharmony_ci        }).width(80).height(35)
182e41f4b71Sopenharmony_ci        Button("Pause").onClick(() => {
183e41f4b71Sopenharmony_ci          this.animatorOptions?.pause();
184e41f4b71Sopenharmony_ci          this.animatorStatus = 'Paused';
185e41f4b71Sopenharmony_ci        }).width(80).height(35)
186e41f4b71Sopenharmony_ci      }.width("100%").height('25%')
187e41f4b71Sopenharmony_ci
188e41f4b71Sopenharmony_ci      Stack() {
189e41f4b71Sopenharmony_ci        Button()
190e41f4b71Sopenharmony_ci          .width(60)
191e41f4b71Sopenharmony_ci          .height(60)
192e41f4b71Sopenharmony_ci          .translate({ x: this.translateX, y: this.translateY })
193e41f4b71Sopenharmony_ci      }
194e41f4b71Sopenharmony_ci      .width("100%")
195e41f4b71Sopenharmony_ci      .height('45%')
196e41f4b71Sopenharmony_ci      .align(Alignment.Start)
197e41f4b71Sopenharmony_ci
198e41f4b71Sopenharmony_ci      Text("Current animation state: "+ this.animatorStatus)
199e41f4b71Sopenharmony_ci    }.width("100%").height('100%')
200e41f4b71Sopenharmony_ci  }
201e41f4b71Sopenharmony_ci}
202e41f4b71Sopenharmony_ci```
203e41f4b71Sopenharmony_ci
204e41f4b71Sopenharmony_ci![en-us_image_0000001599958466](figures/animatorSimple.gif)
205