1e41f4b71Sopenharmony_ci# Animation Frame
2e41f4b71Sopenharmony_ci
3e41f4b71Sopenharmony_ci
4e41f4b71Sopenharmony_ci## Requesting an Animation Frame
5e41f4b71Sopenharmony_ci
6e41f4b71Sopenharmony_ciUse the **requestAnimationFrame** method to request frames on a one-by-one basis. This method accepts a callback as an argument.
7e41f4b71Sopenharmony_ci
8e41f4b71Sopenharmony_ciWhen **runframe** calls **requestAnimationFrame**, the **step** callback with the **timestamp** parameter is passed, and this timestamp iss assigned to **startTime**. When the difference between the **timestamp** and **startTime** is less than the specified value, **requestAnimationFrame** is called again, and the animation stops.
9e41f4b71Sopenharmony_ci
10e41f4b71Sopenharmony_ci```html
11e41f4b71Sopenharmony_ci<!-- xxx.hml -->
12e41f4b71Sopenharmony_ci<div class="container">
13e41f4b71Sopenharmony_ci  <tabs onchange="changecontent">
14e41f4b71Sopenharmony_ci    <tab-content>
15e41f4b71Sopenharmony_ci      <div class="container">
16e41f4b71Sopenharmony_ci        <stack style="width: 300px;height: 300px;margin-top: 100px;margin-bottom: 100px;">
17e41f4b71Sopenharmony_ci          <canvas id="mycanvas" style="width: 100%;height: 100%;background-color: coral;">
18e41f4b71Sopenharmony_ci          </canvas>
19e41f4b71Sopenharmony_ci          <div style="width: 50px;height: 50px;border-radius: 25px;background-color: indigo;position: absolute;left: {{left}};top: {{top}};">
20e41f4b71Sopenharmony_ci          </div>
21e41f4b71Sopenharmony_ci        </stack>
22e41f4b71Sopenharmony_ci        <button type="capsule" value="play" onclick="runframe"></button>
23e41f4b71Sopenharmony_ci      </div>
24e41f4b71Sopenharmony_ci    </tab-content>
25e41f4b71Sopenharmony_ci  </tabs>
26e41f4b71Sopenharmony_ci</div>
27e41f4b71Sopenharmony_ci```
28e41f4b71Sopenharmony_ci
29e41f4b71Sopenharmony_ci```css
30e41f4b71Sopenharmony_ci/* xxx.css */
31e41f4b71Sopenharmony_ci.container {
32e41f4b71Sopenharmony_ci  flex-direction: column;
33e41f4b71Sopenharmony_ci  justify-content: center;
34e41f4b71Sopenharmony_ci  align-items: center;
35e41f4b71Sopenharmony_ci  width: 100%;
36e41f4b71Sopenharmony_ci  height: 100%;
37e41f4b71Sopenharmony_ci}
38e41f4b71Sopenharmony_cibutton{
39e41f4b71Sopenharmony_ci  width: 300px;
40e41f4b71Sopenharmony_ci}
41e41f4b71Sopenharmony_ci```
42e41f4b71Sopenharmony_ci
43e41f4b71Sopenharmony_ci```js
44e41f4b71Sopenharmony_ci// xxx.js
45e41f4b71Sopenharmony_ciexport default {
46e41f4b71Sopenharmony_ci  data: {
47e41f4b71Sopenharmony_ci    timer: null,
48e41f4b71Sopenharmony_ci    left: 0,
49e41f4b71Sopenharmony_ci    top: 0,
50e41f4b71Sopenharmony_ci    flag: true,
51e41f4b71Sopenharmony_ci    animation: null,
52e41f4b71Sopenharmony_ci    startTime: 0,
53e41f4b71Sopenharmony_ci  },
54e41f4b71Sopenharmony_ci  onShow() {
55e41f4b71Sopenharmony_ci    var test = this.$element("mycanvas");
56e41f4b71Sopenharmony_ci    var ctx = test.getContext("2d");
57e41f4b71Sopenharmony_ci    ctx.beginPath();
58e41f4b71Sopenharmony_ci    ctx.moveTo(0, 0);
59e41f4b71Sopenharmony_ci    ctx.lineTo(300, 300);
60e41f4b71Sopenharmony_ci    ctx.lineWidth = 5;
61e41f4b71Sopenharmony_ci    ctx.strokeStyle = "red";
62e41f4b71Sopenharmony_ci    ctx.stroke();
63e41f4b71Sopenharmony_ci  },
64e41f4b71Sopenharmony_ci  runframe() {
65e41f4b71Sopenharmony_ci    this.left = 0;
66e41f4b71Sopenharmony_ci    this.top = 0;
67e41f4b71Sopenharmony_ci    this.flag = true;
68e41f4b71Sopenharmony_ci    this.animation = requestAnimationFrame(this.step);
69e41f4b71Sopenharmony_ci  },
70e41f4b71Sopenharmony_ci  step(timestamp) {
71e41f4b71Sopenharmony_ci    if (this.flag) {
72e41f4b71Sopenharmony_ci      this.left += 5;
73e41f4b71Sopenharmony_ci      this.top += 5;
74e41f4b71Sopenharmony_ci      if (this.startTime == 0) {
75e41f4b71Sopenharmony_ci        this.startTime = timestamp;
76e41f4b71Sopenharmony_ci      }
77e41f4b71Sopenharmony_ci      var elapsed = timestamp - this.startTime;
78e41f4b71Sopenharmony_ci        if (elapsed < 500) {
79e41f4b71Sopenharmony_ci          console.log('callback step timestamp: ' + timestamp);
80e41f4b71Sopenharmony_ci          this.animation = requestAnimationFrame(this.step);
81e41f4b71Sopenharmony_ci        }
82e41f4b71Sopenharmony_ci      } else {
83e41f4b71Sopenharmony_ci        this.left -= 5;
84e41f4b71Sopenharmony_ci        this.top -= 5;
85e41f4b71Sopenharmony_ci        this.animation = requestAnimationFrame(this.step);
86e41f4b71Sopenharmony_ci      }
87e41f4b71Sopenharmony_ci      if (this.left == 250 || this.left == 0) {
88e41f4b71Sopenharmony_ci        this.flag = !this.flag
89e41f4b71Sopenharmony_ci     }
90e41f4b71Sopenharmony_ci    },
91e41f4b71Sopenharmony_ci    onDestroy() {
92e41f4b71Sopenharmony_ci      cancelAnimationFrame(this.animation);
93e41f4b71Sopenharmony_ci    }
94e41f4b71Sopenharmony_ci}
95e41f4b71Sopenharmony_ci```
96e41f4b71Sopenharmony_ci
97e41f4b71Sopenharmony_ci![en-us_image_0000001267767877](figures/en-us_image_0000001267767877.gif)
98e41f4b71Sopenharmony_ci
99e41f4b71Sopenharmony_ci> **NOTE**
100e41f4b71Sopenharmony_ci>
101e41f4b71Sopenharmony_ci> When invoking the callback, the **requestAnimationFrame** method passes the **timestamp** as the first parameter, which indicates the time when **requestAnimationFrame** starts to execute the callback.
102e41f4b71Sopenharmony_ci
103e41f4b71Sopenharmony_ci
104e41f4b71Sopenharmony_ci## Canceling an Animation Frame
105e41f4b71Sopenharmony_ci
106e41f4b71Sopenharmony_ciUse the **cancelAnimationFrame** method to cancel frames on a one-by-one basis. When this method is called, the animation frame request sent through **requestAnimationFrame** will be canceled.
107e41f4b71Sopenharmony_ci
108e41f4b71Sopenharmony_ci```html
109e41f4b71Sopenharmony_ci<!-- xxx.hml -->
110e41f4b71Sopenharmony_ci<div class="container">
111e41f4b71Sopenharmony_ci  <tabs onchange="changecontent">
112e41f4b71Sopenharmony_ci    <tab-content>
113e41f4b71Sopenharmony_ci      <div class="container">
114e41f4b71Sopenharmony_ci        <stack style="width: 300px;height: 300px;margin-top: 100px;margin-bottom: 100px;">
115e41f4b71Sopenharmony_ci          <canvas id="mycanvas" style="width: 100%;height: 100%;background-color: coral;">
116e41f4b71Sopenharmony_ci          </canvas>
117e41f4b71Sopenharmony_ci          <div style="width: 50px;height: 50px;border-radius: 25px;background-color: indigo;position: absolute;left: {{left}};top: {{top}};">
118e41f4b71Sopenharmony_ci          </div>
119e41f4b71Sopenharmony_ci        </stack>
120e41f4b71Sopenharmony_ci        <button type="capsule" value="play" onclick="runframe"></button>
121e41f4b71Sopenharmony_ci      </div>
122e41f4b71Sopenharmony_ci    </tab-content>
123e41f4b71Sopenharmony_ci  </tabs>
124e41f4b71Sopenharmony_ci</div>
125e41f4b71Sopenharmony_ci```
126e41f4b71Sopenharmony_ci
127e41f4b71Sopenharmony_ci```css
128e41f4b71Sopenharmony_ci/* xxx.css */
129e41f4b71Sopenharmony_ci.container {
130e41f4b71Sopenharmony_ci  flex-direction: column;
131e41f4b71Sopenharmony_ci  justify-content: center;
132e41f4b71Sopenharmony_ci  align-items: center;
133e41f4b71Sopenharmony_ci  width: 100%;
134e41f4b71Sopenharmony_ci  height: 100%;
135e41f4b71Sopenharmony_ci}
136e41f4b71Sopenharmony_cibutton{
137e41f4b71Sopenharmony_ci  width: 300px;
138e41f4b71Sopenharmony_ci}
139e41f4b71Sopenharmony_ci```
140e41f4b71Sopenharmony_ci
141e41f4b71Sopenharmony_ci```js
142e41f4b71Sopenharmony_ci// xxx.js
143e41f4b71Sopenharmony_ciexport default {
144e41f4b71Sopenharmony_ci  data: {
145e41f4b71Sopenharmony_ci    timer: null,
146e41f4b71Sopenharmony_ci    left: 0,
147e41f4b71Sopenharmony_ci    top: 0,
148e41f4b71Sopenharmony_ci    flag: true,
149e41f4b71Sopenharmony_ci    animation: null
150e41f4b71Sopenharmony_ci  },
151e41f4b71Sopenharmony_ci  onShow() {
152e41f4b71Sopenharmony_ci    var test = this.$element("mycanvas");
153e41f4b71Sopenharmony_ci    var ctx = test.getContext("2d");
154e41f4b71Sopenharmony_ci    ctx.beginPath();
155e41f4b71Sopenharmony_ci    ctx.moveTo(0, 0);
156e41f4b71Sopenharmony_ci    ctx.lineTo(300, 300);
157e41f4b71Sopenharmony_ci    ctx.lineWidth = 5;
158e41f4b71Sopenharmony_ci    ctx.strokeStyle = "red";
159e41f4b71Sopenharmony_ci    ctx.stroke();
160e41f4b71Sopenharmony_ci  },
161e41f4b71Sopenharmony_ci  runframe() {
162e41f4b71Sopenharmony_ci    this.left = 0;
163e41f4b71Sopenharmony_ci    this.top = 0;
164e41f4b71Sopenharmony_ci    this.flag = true;
165e41f4b71Sopenharmony_ci    this.animation = requestAnimationFrame(this.step);
166e41f4b71Sopenharmony_ci  },
167e41f4b71Sopenharmony_ci  step(timestamp) {
168e41f4b71Sopenharmony_ci    if (this.flag) {
169e41f4b71Sopenharmony_ci      this.left += 5;
170e41f4b71Sopenharmony_ci      this.top += 5;
171e41f4b71Sopenharmony_ci      this.animation = requestAnimationFrame(this.step);
172e41f4b71Sopenharmony_ci    } else {
173e41f4b71Sopenharmony_ci      this.left -= 5;
174e41f4b71Sopenharmony_ci      this.top -= 5;
175e41f4b71Sopenharmony_ci      this.animation = requestAnimationFrame(this.step);
176e41f4b71Sopenharmony_ci    }
177e41f4b71Sopenharmony_ci    if (this.left == 250 || this.left == 0) {
178e41f4b71Sopenharmony_ci      this.flag = !this.flag
179e41f4b71Sopenharmony_ci    }
180e41f4b71Sopenharmony_ci  },
181e41f4b71Sopenharmony_ci  onDestroy() {
182e41f4b71Sopenharmony_ci    cancelAnimationFrame(this.animation);
183e41f4b71Sopenharmony_ci  }
184e41f4b71Sopenharmony_ci}
185e41f4b71Sopenharmony_ci```
186e41f4b71Sopenharmony_ci
187e41f4b71Sopenharmony_ci![en-us_image_0000001223127740](figures/en-us_image_0000001223127740.gif)
188e41f4b71Sopenharmony_ci
189e41f4b71Sopenharmony_ci> **NOTE**
190e41f4b71Sopenharmony_ci>
191e41f4b71Sopenharmony_ci> When **cancelAnimationFrame** is called, a parameter that indicates an ID must be passed.
192