Last active
May 10, 2018 08:47
-
-
Save jokemmy/2dd272444b0c9e10a304701936e2c11a to your computer and use it in GitHub Desktop.
只是记录一下代码,其实现在的浏览器环境已经完全不用写 setTimeout 兼容了
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import is from 'whatitis'; | |
import now from 'performance-now'; | |
const root = typeof window === 'undefined' ? global : window; | |
const vendors = [ 'moz', 'webkit' ]; | |
const suffix = 'AnimationFrame'; | |
let raf = root[`request${suffix}`]; | |
let caf = root[`cancel${suffix}`] || root[`cancelRequest${suffix}`]; | |
for ( let i = 0; !raf && i < vendors.length; i++ ) { | |
const prefix = vendors[i]; | |
raf = root[`${prefix}Request${suffix}`]; | |
caf = root[`${prefix}Cancel${suffix}`] | |
|| root[`${prefix}CancelRequest${suffix}`]; | |
} | |
// Some versions of FF have rAF but not cAF | |
if ( !raf || !caf ) { | |
let chain; | |
let id = 0; | |
let lastTime = 0; | |
const handles = {}; | |
const frameDuration = 1000 / 60; | |
const throwError = ( err ) => () => { | |
throw err; | |
}; | |
const compose = ( callback1, callback2 ) => ( lastTime ) => { | |
return callback1( callback2( lastTime )); | |
}; | |
const handler = ( handle, next ) => ( lastTime ) => { | |
if ( handles[handle] !== false ) { | |
next( lastTime ); | |
} else { | |
handles[handle] = null; | |
} | |
return lastTime; | |
}; | |
const next = ( handled ) => { | |
chain = chain ? compose( handled, chain ) : handled; | |
}; | |
const toCall = function() { | |
const cp = chain; | |
// Clear chain here to prevent | |
// callbacks from appending listeners | |
// to the current frame's chain | |
chain = null; | |
try { | |
cp( lastTime ); | |
} catch ( e ) { | |
setTimeout( throwError( e ), 0 ); | |
} | |
}; | |
raf = function( callback ) { | |
if ( !chain ) { | |
const currTime = now(); | |
const timeToCall = Math.max( 0, frameDuration - ( currTime - lastTime )); | |
lastTime = timeToCall + currTime; | |
root.setTimeout( toCall, Math.round( timeToCall )); | |
} | |
next( handler( ++id, callback )); | |
return id; | |
}; | |
caf = function( arg ) { | |
handles[arg] = false; | |
}; | |
} | |
export default function polyfill() { | |
root.requestAnimationFrame = raf; | |
root.cancelAnimationFrame = caf; | |
return { | |
requestAnimationFrame: root.requestAnimationFrame, | |
cancelAnimationFrame: root.cancelAnimationFrame | |
}; | |
} | |
const { requestAnimationFrame, cancelAnimationFrame } = polyfill(); | |
export function requestAnimFrame( callback ) { | |
let id; | |
const getFrameHandler = () => id; | |
const cancel = () => cancelAnimationFrame( id ); | |
id = requestAnimationFrame( function frameCallback( time ) { | |
callback( Math.round( time * 10 ) / 10, cancel ); | |
id = requestAnimationFrame( frameCallback ); | |
}); | |
return { cancel, getFrameHandler }; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment