Skip to content

Instantly share code, notes, and snippets.

@paulirish
Last active March 22, 2024 00:00
Show Gist options
  • Save paulirish/1579671 to your computer and use it in GitHub Desktop.
Save paulirish/1579671 to your computer and use it in GitHub Desktop.
requestAnimationFrame polyfill
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
// MIT license
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
|| window[vendors[x]+'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() { callback(currTime + timeToCall); },
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
}());
@davidchambers
Copy link

What is the element parameter?

window.requestAnimationFrame = function(callback, element) {

It's unused, and according to MDN the function takes just one argument.

@techniq
Copy link

techniq commented Jun 2, 2015

To better match the timestamp passed to the requestAnimationFrame callback (ie. window.performance.now()), currTime should be adjusted for the navigationStart

var currTime = new Date().getTime() - window.performance.timing.navigationStart;

Without this change my animations on IE9 were not correctly calculating compared to the browsers with native requestAnimationFrame support.

Note: window.performance.timing is only available on IE9+ (which really only applies to IE9 since requestAnimationFrame is already available on IE10+

@techniq
Copy link

techniq commented Jun 4, 2015

@glued
Copy link

glued commented Jul 4, 2015

ES2015 flavored + performance.now()

{

  const vendors = ['ms', 'moz', 'webkit', 'o']
  const af = 'AnimationFrame'
  let lastTime = 0

  if('performance' in window == false)
      window.performance = {}

  if(!Date.now)
    Date.now = () => new Date().getTime()

  if ('now' in window.performance == false){
    let nowOffset = Date.now()

    if(performance.timing && performance.timing.navigationStart)
      nowOffset = performance.timing.navigationStart

    window.performance.now = () => Date.now() - nowOffset
  }

  for(let x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
      const vendor = vendors[x]
      window.requestAnimationFrame  = window[`${vendor}Request${af}`]
      window.cancelAnimationFrame   = window[`${vendor}Cancel${af}`] || window[`${vendor}CancelRequest${af}`]
  }

  if(!window.requestAnimationFrame){
    window.requestAnimationFrame = callback =>{
        const currTime    = Date.now()
        const timeToCall  = Math.max(0, 16 - (currTime - lastTime))
        const id          = window.setTimeout(() => callback(currTime + timeToCall), timeToCall)

        lastTime = currTime + timeToCall
        return id
    }
  }

  if(!window.cancelAnimationFrame)
    window.cancelAnimationFrame = id => clearTimeout(id)

}

@imthenachoman
Copy link

This was very helpful for me. Thanks! I'm using it in a generic animation library I wrote. I hope this is okay. https://github.com/imthenachoman/nAnimation

@190n
Copy link

190n commented Jul 23, 2015

@imthenachoman Same issue as you, what's the license for this? I'm planning to use this in a game engine I'm writing.

@190n
Copy link

190n commented Jul 23, 2015

@imthenachoman It says it's MIT license; you can probably do whatever you want.

@julienetie
Copy link

img
Here's request-frame for anyone looking for a comprehensive solution that should just works on everything.

  • npm / bower request-frame
  • iOS6 fix without user-agent sniffing
  • Normalizes firefox 4 - 10 for cancellation & predictability
  • Polyfill native functions or keep intact via variables (To prevent conflicts with other API usage)
  • IE 5.5+ (tested)
  • AMD support

I believe it's best to use as few requestAnimationFrame instances as possible. I avoided frame rates and delays as they're better utilized outside of the polyfill, (vai the timestamp). Thanks to @darius for the timing tweaks, as well as everyone else on here.

@mikeblakeuk
Copy link

[20:22:43] bower download https://gist.githubusercontent.com/paulirish/1579671/raw/3d42a3a76ed09890434a07be2212f376959e616f/rAF.js

Anyone else getting this:

Error 503 backend read error

backend read error

Guru Mediation:

Details: cache-lcy1125-LCY 1439843293 3968273849

Varnish cache server

@lenville
Copy link

lenville commented Sep 7, 2015

Due to an unconfirmed bug in OldIE(maybe the poor performance), many tasks were delaying running.

There are two intended bad Fibonacci demos.

  1. Check the original one in IE8(or lower version), then you may find that timeToCall is gradually growing bigger and bigger.

    raf_without_limitation

    I've made a little change to this code.
    https://gist.github.com/lenville/9e13e63af075c145d662/revisions#diff-0

    // line 20
    var timeToCall = Math.max(0, 16 - Math.abs(currTime - lastTime));
  2. Check the revision.

    Now everything works very well, like this:
    raf_with_limitation

@borgeslt
Copy link

In this article, David Geary implements a interesting version of polyfill.
http://www.ibm.com/developerworks/library/j-html5-game2/#N101B4

What do you think about it?

@milosdjakonovic
Copy link

I've written a solution that doesn't queue each callback separately but execute all scheduled for next frame simultaneously:

https://github.com/milosdjakonovic/requestAnimationFrame-polyfill

Second (third, fourth...) opinion and eyeball check would do good.

@jlmakes
Copy link

jlmakes commented Dec 12, 2016

In most situations I use miniraf

@elizad
Copy link

elizad commented Jan 20, 2017

Maybe I'm still missing something but for me the polyfill is not working right now and I am triong to figure out what is missing

Uncaught SyntaxError: Missing initializer in const declaration

@vennapusaravali
Copy link

Hai , i am new to angular2. i have a conflict in loading the angular2 webapp in safari browser. Actually where to use this code in the code so that i can get rid of this browser problem. is this also the solution for improper loading of c3 charts in certain browsers like safari and microsoft edge. please help me out and thanks in advance.

@marcusbelcher
Copy link

Hi Vennapusaravali,

More suitable for the Angular 4 repo, however if you checkout this JS file and add the script to angular-cli.jsons "scripts": [ ".../path/to/this/file/rAF.js" ] it should load correctly. More info can be found here.

@williansmartins
Copy link

Hello, can someone help me with a question in my website? I don't know where is the issue list, or who I can ask. My website is not working the parallax.js (http://memphisnet.com.br/3.0/)

Thanks advice

@dashkevych
Copy link

Hi guys,

Anyone know the answer to this question: https://stackoverflow.com/questions/52508261/do-we-need-to-clear-a-timeout-when-using-requestanimationframe-polyfill ? Would like to hear a professional opinion.

Thanks

@smrtrnx
Copy link

smrtrnx commented Jan 19, 2019

I've been reading a lot of the comments but I am kinda bit confused now which code to be implemented.

@jalbam
Copy link

jalbam commented Jul 21, 2019

Hello,

I just adapted Paul Irish's polyfill to work with high resolution timing automatically (when possible) and improved the performance a little bit.

It can work with the following window.performance.now polyfill: https://gist.github.com/jalbam/cc805ac3cfe14004ecdf323159ecf40e

Here it is:

'use strict';

// requestAnimationFrame polyfill by Erik Möller.
// Fixes from Paul Irish, Tino Zijdel, Andrew Mao, Klemen Slavic, Darius Bacon and Joan Alba Maldonado.
// Adapted from https://gist.github.com/paulirish/1579671 which derived from
// http://paulirish.com/2011/requestanimationframe-for-smart-animating/
// http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
// Added high resolution timing. This window.performance.now() polyfill can be used: https://gist.github.com/jalbam/cc805ac3cfe14004ecdf323159ecf40e
// MIT license
// Gist: https://gist.github.com/jalbam/5fe05443270fa6d8136238ec72accbc0
(function() {
	var vendors = ['webkit', 'moz', 'ms', 'o'], vp = null;
	for (var x = 0; x < vendors.length && !window.requestAnimationFrame && !window.cancelAnimationFrame; x++)
	{
		vp = vendors[x];
		window.requestAnimationFrame = window.requestAnimationFrame || window[vp + 'RequestAnimationFrame'];
		window.cancelAnimationFrame = window.cancelAnimationFrame || window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame'];
	}
	if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) //iOS6 is buggy.
	{
		var lastTime = 0;
		window.requestAnimationFrame = function(callback, element)
		{
			var now = window.performance.now();
			var nextTime = Math.max(lastTime + 16, now);
			return setTimeout(function() { callback(lastTime = nextTime); }, nextTime - now);
		};
		window.cancelAnimationFrame = clearTimeout;
	}
}());

You can found it in this gist: https://gist.github.com/jalbam/5fe05443270fa6d8136238ec72accbc0

Any comments are welcome. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment