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 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 188e41f4b71Sopenharmony_ci 189e41f4b71Sopenharmony_ci> **NOTE** 190e41f4b71Sopenharmony_ci> 191e41f4b71Sopenharmony_ci> When **cancelAnimationFrame** is called, a parameter that indicates an ID must be passed. 192