public
Last active

Paul Irish's requestAnimFrame shim improved with suport for element visibility and window blur detection

  • Download Gist
animframe.js
JavaScript
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
// requestAnimFrame shim layer by Paul Irish
// Support for element visibility and window blur detection by Juerg Lehni
 
(function() {
// Chrome shipped without the time arg in m10
var webkitRequest = window.webkitRequestAnimationFrame;
if (webkitRequest) {
webkitRequest(function(time) {
if (time == undefined)
webkitRequest = null;
});
}
 
window.requestAnimFrame = (function() {
var request = window.requestAnimationFrame || webkitRequest ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame;
if (request)
return request;
 
// So we need to fake it. Define helper functions first:
 
// Checks if element is visibile in current viewport
function isVisible(element) {
var doc = document.getElementsByTagName(
document.compatMode == 'CSS1Compat' ? 'html' : 'body')[0],
rect1 = {
x: window.pageXOffset || doc.scrollLeft,
y: window.pageYOffset || doc.scrollTop,
width: window.innerWidth || doc.clientWidth,
height: window.innerHeight || doc.clientHeight
},
rect2 = {
x: 0, y: 0,
width: element.offsetWidth,
height: element.offsetHeight
};
// Add offsets
for (var el = element; el;
rect2.x += el.offsetLeft, rect2.y += el.offsetTop,
el = el.offsetParent) {}
// See if the two rectangle intersect
return rect1.x + rect1.width > rect2.x
&& rect1.y + rect1.height > rect2.y
&& rect1.x < rect2.x + rect2.width
&& rect1.y < rect2.y + rect2.height;
}
 
// Installs event listeners on the window
function addEvent(type, func) {
if (window.addEventListener) {
addEventListener(type, func, false);
} else if (window.attachEvent) {
attachEvent('on' + type, func);
}
}
 
var focused = true;
addEvent('focus', function() {
focused = true;
});
addEvent('blur', function() {
focused = false;
});
return function(callback, element) {
window.setTimeout(function() {
callback(+new Date);
}, focused && (!element || isVisible(element)) ? 1000 / 60 : 1000);
};
})();
})();

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.