Introduction
What is requestAnimationFrame
requestAnimationFrame
is an API used by browsers for timed loop operations, usually used for animation and game development. It will centralize all DOM operations in each frame, update them all at once before redrawing, and associate them with the browser’s redraw operation.
Why use requestAnimationFrame instead of setTimeout or setInterval
Compared with setTimeout
or setInterval
, requestAnimationFrame
has the following advantages:
- Call the callback function through the system time interval. There is no need to worry about system load and blocking issues. The system will automatically adjust the callback frequency.
- Scheduled and optimized internally by the browser, the performance is higher and consumes less CPU and GPU resources.
- Avoid frame loss, ensure continuous execution of callbacks, and achieve smoother animation effects.
- Automatically merge multiple callbacks to avoid unnecessary overhead.
- Synchronized with browser refresh, no callback will be executed when the browser page is not visible.
Advantages and applicable scenarios of requestAnimationFrame
requestAnimationFrame
is most suitable for animations that require continuous high-frequency execution, such as game development, data visualization animation, etc. It is consistent with the browser refresh cycle and will not cause animation freezes due to uneven intervals.
How to use
Basic syntax of requestAnimationFrame
requestAnimationFrame
receives a callback function as a parameter, which will be executed before the next redraw of the browser.
const animation = () => { //Execute animation requestAnimationFrame(animation); } requestAnimationFrame(animation);
The above code will continuously call requestAnimationFrame
and execute the callback function before each browser redraw to achieve continuous animation effects.
How to use requestAnimationFrame in animation
You can update the state of the animation in the callback function, then clear the previous frame and draw the frame in the new state:
let angle = 0; const render = () => { ctx.clearRect(0, 0, width, height); // Clear the previous frame // update status angle + = delta; ctx.beginPath(); ctx.arc(x, y, radius, 0, angle); ctx.stroke(); requestAnimationFrame(render); }
In this way, by updating parameters in each callback, continuous animation of the object can be achieved.
requestAnimationFrame callback function parameters
The callback function of requestAnimationFrame
will receive a parameter, which is a timestamp in milliseconds, representing the time when requestAnimationFrame
was triggered. The time interval between two frames can be calculated based on this timestamp to adjust the animation speed.
let prevTimestamp; const render = timestamp => { if (!prevTimestamp) prevTimestamp = timestamp; const delta = timestamp - prevTimestamp; // Calculate speed based on time interval x + = speed * delta; prevTimestamp = timestamp; requestAnimationFrame(render); }
Performance optimization
Avoid a large number of calculations in the requestAnimationFrame callback function
Since the callback of requestAnimationFrame
will be executed synchronously in a high-priority thread, if there are a lot of calculations in the callback function, this thread will be blocked, causing the page to freeze.
That is, if the execution time of requestAnimationFrame
‘s callback function exceeds one frame (usually 16.67 milliseconds, because the browser usually refreshes at about 60 frames per second), it may cause animation performance to decrease, and may occur Frame drops ultimately affect the user experience. This is because the time of each frame of the browser is limited. If the execution time of the callback function is too long, the preparation and drawing time of the next frame will be compressed, causing the animation to freeze.
In general, you should try to avoid performing time-consuming operations in the callback function of requestAnimationFrame
. To solve this problem, here are some strategies you can adopt:
-
Optimize callback functions: Make callback functions as short as possible to avoid unnecessary calculations or loops. Only perform necessary animation-related operations in the callback.
-
Frame processing: If the animation requires processing a large amount of data or computationally complex operations, these operations can be spread out into multiple
requestAnimationFrame
callbacks to avoid long-term occupancy. -
Web Workers: Execute time-consuming calculations in a separate Web Worker thread so as not to affect the main thread and animation rendering.
-
Frame rate control: If the callback function takes a long time, you can control the frame rate of the animation based on the actual execution time of the callback function. Reduce the speed of animated objects or reduce rendering quality to accommodate current performance.
-
Monitor performance: Use browser developer tools to monitor performance to find out which operations are causing callback functions to take too long to execute.
In summary, ensure that the execution time of the requestAnimationFrame
callback function is as short as possible to ensure smooth animation and performance.
Use hardware acceleration to optimize animation performance
Enabling GPU
accelerated rendering can significantly improve animation performance.
.animated { transform: translateZ(0); /* Enable hardware acceleration */ }
How to achieve smooth animation effects on different devices
You can calculate the interval delta
between this frame and the previous frame based on the timestamp of the requestAnimationFrame
callback, and adopt different methods based on the value of delta
Optimization means:
delta
is extremely small, indicating that this frame takes too long, which may cause frame drops and reduce the moving speed or image quality of animated objects.delta
gradually becomes larger, indicating that the animation gradually becomes stuck, which can reduce the number or complexity of animation objects.delta
fluctuates greatly, indicating insufficient system resources. Simple animation can be used as a downgrade strategy.
Comparison with other animation libraries
The difference between requestAnimationFrame and setTimeout/setInterval
setTimeout/setInterval
is triggered at a fixed time interval,requestAnimationFrame
relies on system refresh schedulingsetTimeout/setInterval
will ignore whether the page is visible,requestAnimationFrame
will stop refreshingsetTimeout/setInterval
is difficult to avoid frame loss.requestAnimationFrame
is synchronized with refresh to avoid frame loss.
Combined use of requestAnimationFrame and CSS animation
requestAnimationFrame
can be used to update animation status and implement complex animation logic, while CSS animation is used to declaratively define animation style changes. The two can be used together to achieve richer animation effects.
Practical application
Use requestAnimationFrame to achieve common animation effects
You can use requestAnimationFrame
to achieve effects such as object trajectory animation, SVG graphic animation, and loading animation.
// Ball tailing effect const positions = []; const render = () => { //Add new location positions.push({x, y}); if (positions.length > 10){ positions.shift(); } // Render the ball ctx.clearRect(0, 0, width, height); positions.forEach(pos => ctx.fillRect(pos.x, pos.y, 10, 10)); requestAnimationFrame(render); } // SVG drawing animation let length = 0; const render = () => { length + = 4; svgLine.setAttribute("stroke-dasharray", length); if (length < 300) { requestAnimationFrame(render); } } requestAnimationFrame(render); // Progress bar loading animation let progress = 0; const render = () => { progress + = 1; loadBar.style.width = progress + '%'; if(progress < 100) { requestAnimationFrame(render); } } requestAnimationFrame(render);
Application of requestAnimationFrame in game development
Games require very smooth graphics and real-time response. This is the advantage of requestAnimationFrame
. It can be used to implement operations such as object movement, collision detection, and frame number control in the game.
//Aircraft shooting animation const update = () => { // Bullet position update bullets.forEach(bullet => { bullet.position + = speed; }) // Aircraft position update aircraft.position + = delta * speed; // Draw all elements render(bullets, aircraft); requestAnimationFrame(update); }
Application of requestAnimationFrame in responsive design
You can use requestAnimationFrame
to perform responsive layout changes more smoothly and avoid the visual impact caused by sudden large movements of the layout.
let width = 500; const resize = () => { width = container.clientWidth; box.style.width = width + "px"; requestAnimationFrame(resize); } window.addEventListener("resize", resize);
Compatibility and subsequent development
Browser compatibility of requestAnimationFrame
requestAnimationFrame
is now widely supported and can be used directly. For browsers that do not support it, you can use setTimeout
to simulate requestAnimationFrame
.
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || (cb => setTimeout(cb, 1000/60));
The future development trend of requestAnimationFrame
In the future, requestAnimationFrame
may support setting frame rates, enhancing scheduling algorithms, etc. to improve animation performance. Web worker threads also bring more room for optimization.
Browser manufacturers are also continuing to improve related APIs, such as setTimeout
and requestIdleCallback
, which are also moving towards more precise scheduling.
How to achieve similar effects in browsers that do not support requestAnimationFrame
You can implement a polyfill
yourself:
window.requestAnimationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || (cb => setTimeout(cb, 1000/60));
This will allow you to use requestAnimationFrame
in most browsers. For older browsers, you can use setInterval
to simulate, but the effect will be rough.
Summary
requestAnimationFrame
is a good helper for implementing complex animations. You must master its usage and optimization skills to maximize its effectiveness. At the same time, better performance can also be achieved by combining other technologies such as CSS animation, Web Worker, etc. With the continuous advancement of browsers, requestAnimationFrame
also has great potential for expansion.
This article was first published on the public account “Front-End Dashi Brother”. Please indicate this information when reprinting.