diff options
Diffstat (limited to 'src/animation/Animator.js')
-rw-r--r-- | src/animation/Animator.js | 85 |
1 files changed, 85 insertions, 0 deletions
diff --git a/src/animation/Animator.js b/src/animation/Animator.js new file mode 100644 index 0000000..fdb2326 --- /dev/null +++ b/src/animation/Animator.js @@ -0,0 +1,85 @@ +import Queue from './Queue.js' + +const Animator = { + nextDraw: null, + frames: new Queue(), + timeouts: new Queue(), + timer: window.performance || window.Date, + transforms: [], + + frame (fn) { + // Store the node + var node = Animator.frames.push({ run: fn }) + + // Request an animation frame if we don't have one + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw) + } + + // Return the node so we can remove it easily + return node + }, + + transform_frame (fn, id) { + Animator.transforms[id] = fn + }, + + timeout (fn, delay) { + delay = delay || 0 + + // Work out when the event should fire + var time = Animator.timer.now() + delay + + // Add the timeout to the end of the queue + var node = Animator.timeouts.push({ run: fn, time: time }) + + // Request another animation frame if we need one + if (Animator.nextDraw === null) { + Animator.nextDraw = window.requestAnimationFrame(Animator._draw) + } + + return node + }, + + cancelFrame (node) { + Animator.frames.remove(node) + }, + + clearTimeout (node) { + Animator.timeouts.remove(node) + }, + + _draw (now) { + // Run all the timeouts we can run, if they are not ready yet, add them + // to the end of the queue immediately! (bad timeouts!!! [sarcasm]) + var nextTimeout = null + var lastTimeout = Animator.timeouts.last() + while ((nextTimeout = Animator.timeouts.shift())) { + // Run the timeout if its time, or push it to the end + if (now >= nextTimeout.time) { + nextTimeout.run() + } else { + Animator.timeouts.push(nextTimeout) + } + + // If we hit the last item, we should stop shifting out more items + if (nextTimeout === lastTimeout) break + } + + // Run all of the animation frames + var nextFrame = null + var lastFrame = Animator.frames.last() + while ((nextFrame !== lastFrame) && (nextFrame = Animator.frames.shift())) { + nextFrame.run() + } + + Animator.transforms.forEach(function (el) { el() }) + + // If we have remaining timeouts or frames, draw until we don't anymore + Animator.nextDraw = Animator.timeouts.first() || Animator.frames.first() + ? window.requestAnimationFrame(Animator._draw) + : null + } +} + +export default Animator |