A recent look at the source code of some antDV components shows that setTimeout is used instead of requestAnimationFrame; Let’s see how this works;

First requestAnimationFrame The biggest advantage of requestAnimationFrame over setTimeout is that it is up to the browser to decide when to execute the callback function, that is, to keep up with the browser’s refresh pace.

Second, CPU energy saving: When the page is hidden (hidden) or minimized (background tabs), setTimeout still performs the animation task in the background (but the execution time is delayed). Since the page is not visible or available at this time, there is no point in refreshing the animation. It also wastes CPU resources and battery life. RequestAnimationFrame is completely different. When the page is inactive, the screen drawing task of the page is also suspended by the browser, so the requestAnimationFrame that follows the steps of the browser also stops rendering. When the page is active, The animation picks up where it left off, saving CPU overhead and improving performance and battery life.

// getRequestAnimationFrame.js
/ / determine whether support requestAnimationFrame cancelAnimationFrame | setTimeout/clearTimeout, according to support the return to the corresponding method syntax

const availablePrefixs = ['moz'.'ms'.'webkit']

function requestAnimationFramePolyfill () {
  let lastTime = 0
  return function (callback) {
    const currTime = new Date().getTime()
    const timeToCall = Math.max(0.16 - (currTime - lastTime))
    const id = window.setTimeout(function () {
      callback(currTime + timeToCall)
    }, timeToCall)
    lastTime = currTime + timeToCall
    return id
  }
}

export default function getRequestAnimationFrame () {
  if (typeof window= = ='undefined') {
    return () = >{}}if (window.requestAnimationFrame) {
    // https://github.com/vuejs/vue/issues/4465
    return window.requestAnimationFrame.bind(window)}const prefix = availablePrefixs.filter(key= > `${key}RequestAnimationFrame` in window) [0]

  return prefix ? window[`${prefix}RequestAnimationFrame`] : requestAnimationFramePolyfill()
}

export function cancelRequestAnimationFrame (id) {
  if (typeof window= = ='undefined') {
    return null
  }
  if (window.cancelAnimationFrame) {
    return window.cancelAnimationFrame(id)
  }
  const prefix = availablePrefixs.filter(
    key= > `${key}CancelAnimationFrame` in window || `${key}CancelRequestAnimationFrame` in window) [0]

  return prefix
    ? (
      window[`${prefix}CancelAnimationFrame`] | |window[`${prefix}CancelRequestAnimationFrame`]
    ).call(this, id)
    : clearTimeout(id)
}

Copy the code
// requestAnimationTimeout.js
// Create a custom method requestAnimationTimeout to delay execution
CancelAnimationTimeout cancelAnimationTimeout is used to clear requestAnimationTimeout that has not yet been executed
import getRequestAnimationFrame, {
  cancelRequestAnimationFrame
} from './getRequestAnimationFrame'

const dataSetTimeout = getRequestAnimationFrame()

export const cancelAnimationTimeout = frame= > cancelRequestAnimationFrame(frame.id)

export const requestAnimationTimeout = (callback, delay = 0) = > {
  const start = Date.now()
  function timeout () {
    if (Date.now() - start >= delay) {
      callback.call()
    } else {
      obj.id = dataSetTimeout(timeout)
    }
  }

  const obj = {
    id: dataSetTimeout(timeout)
  }

  return obj
}
Copy the code

Use directly introducing requestAnimationTimeout. Js export its {requestAnimationTimeout, cancelAnimationTimeout} method;

The requestAnimationTimeout method returns an object containing an ID value; If cancelAnimationTimeout is required, cancelAnimationTimeout(/* The requestAnimationTimeout method returns an object as argument */);

Hope can be helpful to you!