overscroll
Version:
108 lines (95 loc) • 2.87 kB
JavaScript
import is from 'whatitis';
import invariant from 'invariant';
import now from 'performance-now';
var root = typeof window === 'undefined' ? global : window;
var vendors = ['moz', 'webkit'];
var suffix = 'AnimationFrame';
var raf = root['request' + suffix];
var caf = root['cancel' + suffix] || root['cancelRequest' + suffix];
for (var i = 0; !raf && i < vendors.length; i++) {
var 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) {
var chain = void 0;
var id = 0;
var lastTime = 0;
var handles = {};
var frameDuration = 1000 / 60;
var throwError = function throwError(err) {
return function () {
throw err;
};
};
var compose = function compose(callback1, callback2) {
return function (lastTime) {
return callback1(callback2(lastTime));
};
};
var handler = function handler(handle, next) {
return function (lastTime) {
if (handles[handle] !== false) {
next(lastTime);
} else {
handles[handle] = null;
}
return lastTime;
};
};
var next = function next(handled) {
chain = chain ? compose(handled, chain) : handled;
};
var toCall = function toCall() {
var 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 raf(callback) {
if (!chain) {
var currTime = now();
var timeToCall = Math.max(0, frameDuration - (currTime - lastTime));
lastTime = timeToCall + currTime;
root.setTimeout(toCall, Math.round(timeToCall));
}
next(handler(++id, callback));
return id;
};
caf = function caf(arg) {
handles[arg] = false;
};
}
export default function polyfill() {
root.requestAnimationFrame = raf;
root.cancelAnimationFrame = caf;
return {
requestAnimationFrame: root.requestAnimationFrame,
cancelAnimationFrame: root.cancelAnimationFrame
};
}
var _polyfill = polyfill(),
requestAnimationFrame = _polyfill.requestAnimationFrame,
cancelAnimationFrame = _polyfill.cancelAnimationFrame;
export function requestAnimFrame(callback) {
invariant(is.Function(callback), 'Expecting callback of requestAnimFrame is a function.');
var id = void 0;
var getFrameHandler = function getFrameHandler() {
return id;
};
var cancel = function cancel() {
return cancelAnimationFrame(id);
};
id = requestAnimationFrame(function frameCallback(time) {
callback(Math.round(time * 10) / 10, cancel);
id = requestAnimationFrame(frameCallback);
});
return { cancel: cancel, getFrameHandler: getFrameHandler };
}