如果某个函数被传递到
requestAnimationFrame()
,该函数如何检测到它正在动画帧内被调用?
f.e.
function someFunction() {
if (/* What goes here? */) {
console.log('Inside animation frame.')
}
else {
console.log('Not inside animation frame.')
}
}
// The following lines should not be modified for the answer.
someFunction() // logs "Not inside animation frame."
requestAnimationFrame(someFunction) // eventually logs "Inside animation frame."
最后两行不应修改。我很想知道是否可以检测到这种情况,而不需要用户记住以两种不同的方式使用该功能。最终用户应该像平常一样使用该函数,而不知道我的函数检测到用例。
目前无法获取 Javascript 中调用代码的上下文,因此除非您进行更改,否则您无法执行您想要的操作
requestAnimationFrame()
,但值得庆幸的是您可以做到这一点。试试这个...
// save a reference to the existing method and then override it...
window._requestAnimationFrame = window.requestAnimationFrame;
window.requestAnimationFrame = function(callback) {
return window._requestAnimationFrame(function() {
callback(true);
});
}
function someFunction() {
if (arguments.length && arguments[0]) {
console.log('Inside animation frame.')
}
else {
console.log('Not inside animation frame.')
}
}
someFunction();
requestAnimationFrame(someFunction);
将我自己的答案放在这里以供参考(感谢@phuzi,@Archer和@spender):
// save a reference to the existing method and then override it...
window.requestAnimationFrame = function (raf) { return function(callback) {
return raf(function(time) {
callback(time, true);
});
}}(window.requestAnimationFrame.bind(window))
function someFunction(time, inFrame = false) {
if (inFrame) {
console.log('Inside animation frame.')
}
else {
console.log('Not inside animation frame.')
}
}
someFunction(); // logs "Not inside animation frame."
someFunction(63245); // still logs "Not inside animation frame."
requestAnimationFrame(someFunction); // eventually logs "Inside animation frame."
您可以
bind
您传递给 requestAnimationFrame
的函数。
function someFunction(isInsideAnimationFrame, domHighResTimestamp) {
if (isInsideAnimationFrame) {
console.log('Inside animation frame.')
}
else {
console.log('Not inside animation frame.')
}
}
someFunction() // logs "Not inside animation frame."
requestAnimationFrame(someFunction.bind(null, true)) // eventually logs "Inside animation frame."
有关其工作原理的详细信息,请参阅 Function.prototype.bind。
更新
查看 window.requestAnimationFrame 的文档,回调即
someFunction
将使用 DOMHighResTimeStamp
进行调用,即 .
someFunction
可以用 检测到这一点
function someFunction(domHighResTimestamp) {
if (domHighResTimestamp) {
console.log('Inside animation frame.')
}
else {
console.log('Not inside animation frame.')
}
}
不幸的是,不能保证使用
someFunction
的人不会将其称为传递值。
你可以这样做:
它导出
getIsDuringAnimationFrame
并修补原生 requestAnimationFrame
功能。
let animationFrameCallbacksCount = 0;
const originalRequestAnimationFrame = window.requestAnimationFrame.bind(window);
window.requestAnimationFrame = function requestAnimationFrame(callback: (time: number) => void) {
return originalRequestAnimationFrame((time) => {
try {
animationFrameCallbacksCount++;
callback(time);
} finally {
animationFrameCallbacksCount--;
}
})
}
export function getIsDuringAnimationFrame() {
return animationFrameCallbacksCount > 0;
}