diff options
Diffstat (limited to 'src/animator.js')
-rw-r--r-- | src/animator.js | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/src/animator.js b/src/animator.js new file mode 100644 index 0000000..4d37008 --- /dev/null +++ b/src/animator.js @@ -0,0 +1,89 @@ +/* global requestAnimationFrame */ + +SVG.Animator = { + nextDraw: null, + frames: new SVG.Queue(), + timeouts: new SVG.Queue(), + frameCount: 0, + timeoutCount: 0, + timer: window.performance || window.Date, + + frame: function (fn) { + SVG.Animator.frames.push({ + id: SVG.Animator.frameCount, + run: fn + }) + + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + } + + return ++SVG.Animator.frameCount + }, + + timeout: function (fn, delay) { + delay = delay || 0 + + // Work out when the event should fire + var time = SVG.Animator.timer.now() + delay + + // Add the timeout to the end of the queue + var thisId = SVG.Animator.timeoutCount++ + SVG.Animator.timeouts.push({ + id: thisId, + run: fn, + time: time + }) + + // Request another animation frame if we need one + if (SVG.Animator.nextDraw === null) { + SVG.Animator.nextDraw = requestAnimationFrame(SVG.Animator._draw) + } + + return thisId + }, + + cancelTimeout: function (id) { + // Find the index of the timeout to cancel and remove it + var index = SVG.Animator.timeouts.remove( + function (t) { + return t.id === id + } + ) + return index + }, + + _draw: function (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 tracking = true + var nextTimeout = null
+ var lastTimeout = SVG.Animator.timeouts.last() + while ((nextTimeout = SVG.Animator.timeouts.shift())) { + + // Run the timeout if its time, or push it to the end + if (now > nextTimeout.time) { + nextTimeout.run() + } else { + SVG.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 frames available up until this point + var lastFrame = SVG.Animator.frames.last() + var lastFrameId = SVG.Animator.frameCount + while (SVG.Animator.frames.first() && SVG.Animator.frames.first().id < lastFrameId) { + var nextFrame = SVG.Animator.frames.shift() + nextFrame.run(now) + } + + // If we have remaining timeouts or frames, draw until we don't anymore + SVG.Animator.nextDraw = SVG.Animator.timeouts.length > 0 || SVG.Animator.frames.length > 0 + ? requestAnimationFrame(SVG.Animator._draw) + : null + } +} |