最近看antdv 某些组件源码的时候发现,是使用requestAnimationFrame 来代替 setTimeout;下面我们就来看看是如何实现的;
首先 requestAnimationFrame与setTimeout相比,requestAnimationFrame 最大的优势是由浏览器来决定回调函数的执行时机,即紧跟浏览器的刷新步调。
其次,CPU节能:使用setTimeout实现的动画,当页面被隐藏(隐藏的)或最小化(后台标签页)时,setTimeout仍然在后台执行动画任务(只不过执行时间有所延迟),由于此时页面处于不可见或不可用状态,刷新动画是没有意义的,而且还浪费 CPU 资源和电池寿命。而requestAnimationFrame则完全不同,当页面处于未激活的状态下,该页面的屏幕绘制任务也会被浏览器暂停,因此跟着浏览器步伐走的requestAnimationFrame也会停止渲染,当页面被激活时,动画就从上次停留的地方继续执行,有效节省了 CPU 开销,提升性能和电池寿命。
// getRequestAnimationFrame.js
// 判断是否支持 requestAnimationFrame/cancelAnimationFrame |setTimeout/clearTimeout,根据支持语法返回对应的方法
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)
}
// requestAnimationTimeout.js
// 创建自定 方法 requestAnimationTimeout 用于延迟执行
// 创建自定 方法 cancelAnimationTimeout 用于清除还未执行的requestAnimationTimeout
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
}
使用就直接引入 requestAnimationTimeout.js 导出其 {requestAnimationTimeout, cancelAnimationTimeout } 方法;
requestAnimationTimeout 方法会返回一个 object 对象, 包含一个id值;如果需要取消执行,cancelAnimationTimeout(/* 将 requestAnimationTimeout 方法会返回一个 object 对象,作为参数*/);
希望能对你有帮助!
今天的文章封装 requestAnimationFrame 来代替 setTimeout分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/19929.html