UNPKG

hae

Version:

Mobile web UI based on Vux

142 lines (124 loc) 4.42 kB
const time = Date.now || function () { return +new Date() } let running = {} let counter = 1 let desiredFrames = 60 let millisecondsPerSecond = 1000 // 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 if (typeof window !== 'undefined') { ;(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) } } }()) } export default { // A requestAnimationFrame wrapper / polyfill. requestAnimationFrame: (function () { if (typeof window !== 'undefined') { var requestFrame = window.requestAnimationFrame return function (callback, root) { requestFrame(callback, root) } } })(), // Stops the given animation. stop (id) { var cleared = running[id] != null if (cleared) { running[id] = null } return cleared }, // Whether the given animation is still running. isRunning (id) { return running[id] != null }, // Start the animation. start (stepCallback, verifyCallback, completedCallback, duration, easingMethod, root) { var _this = this var start = time() var lastFrame = start var percent = 0 var dropCounter = 0 var id = counter++ if (!root) { root = document.body } // Compacting running db automatically every few new animations if (id % 20 === 0) { var newRunning = {} for (var usedId in running) { newRunning[usedId] = true } running = newRunning } // This is the internal step method which is called every few milliseconds var step = function (virtual) { // Normalize virtual value var render = virtual !== true // Get current time var now = time() // Verification is executed before next animation step if (!running[id] || (verifyCallback && !verifyCallback(id))) { running[id] = null completedCallback && completedCallback(desiredFrames - (dropCounter / ((now - start) / millisecondsPerSecond)), id, false) return } // For the current rendering to apply let's update omitted steps in memory. // This is important to bring internal state variables up-to-date with progress in time. if (render) { var droppedFrames = Math.round((now - lastFrame) / (millisecondsPerSecond / desiredFrames)) - 1 for (var j = 0; j < Math.min(droppedFrames, 4); j++) { step(true) dropCounter++ } } // Compute percent value if (duration) { percent = (now - start) / duration if (percent > 1) { percent = 1 } } // Execute step callback, then... var value = easingMethod ? easingMethod(percent) : percent if ((stepCallback(value, now, render) === false || percent === 1) && render) { running[id] = null completedCallback && completedCallback(desiredFrames - (dropCounter / ((now - start) / millisecondsPerSecond)), id, percent === 1 || duration == null) } else if (render) { lastFrame = now _this.requestAnimationFrame(step, root) } } // Mark as running running[id] = true // Init first step _this.requestAnimationFrame(step, root) // Return unique animation ID return id } }