Created
January 2, 2012 09:34
-
-
Save nilium/1550039 to your computer and use it in GitHub Desktop.
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
| class AnimationBlock | |
| constructor: (@fps) -> | |
| @millisecondsPerFrame = 1000.0 / fps | |
| @animations = [] | |
| @interval = null | |
| @callback => | |
| time = AnimationBlock.getTime() | |
| animsCopy = @animations.slice(0) # copy the array | |
| for anim in animsCopy | |
| anim.tick time if anim.isRunning() | |
| @removeAnimation anim if not anim.isRunning() | |
| if @animations.length > 0 and AnimationBlock.requestAnimationFrame? | |
| AnimationBlock.requestAnimationFrame(@callback) | |
| @requestAnimationFrame: (-> | |
| reqFrame = window.requestAnimationFrame or | |
| window.webkitRequestAnimationFrame or | |
| window.mozRequestAnimationFrame or | |
| window.oRequestAnimationFrame or | |
| null | |
| if reqFrame? | |
| return ((callback) -> return reqFrame.call(window, callback)) | |
| else | |
| return null)() | |
| @getTime: (-> | |
| if window.mozRequestAnimationFrame? | |
| return (-> return window.mozAnimationStartTime) | |
| else | |
| return -> return new Date().getTime())() | |
| @setInterval: (callback, milliseconds) -> | |
| return setInterval(callback, milliseconds) | |
| @clearInterval: (interval) -> clearInterval(interval) | |
| addAnimation: (newAnim) -> | |
| for anim in @animations | |
| return if anim is newAnim | |
| @animations.push anim | |
| anim.start() unless anim.isRunning() | |
| if @animations.length is 1 | |
| if AnimationBlock.requestAnimationFrame? | |
| AnimationBlock.requestAnimationFrame(@callback) | |
| else | |
| @interval = AnimationBlock.setInterval(@callback, @millisecondsPerFrame) | |
| removeAnimation: (animToRemove) -> | |
| # not very pretty | |
| @animations = for anim in animations.slice(0) when anim isnt animToRemove | |
| anim | |
| if @animations.length is 0 and not AnimationBlock.requestAnimationFrame? | |
| AnimationBlock.clearInterval @interval | |
| class Animation | |
| constructor: (duration, @responder, @timingFunc) -> | |
| @running = no | |
| @start = 0 | |
| @elapsed = 0 | |
| @setDuration(duration) | |
| @block = null | |
| @chain = [] | |
| @timingFunc ?= Animation.TIMING.linear() | |
| duration: -> | |
| return @duration | |
| setDuration: (@duration) -> | |
| @duration = 1 if @duration < 1 | |
| @durationOverOne = 1.0 / @duration | |
| return this | |
| stop: -> | |
| return this unless @running | |
| @running = no | |
| @elapsed = AnimationBlock.getTime() - @start | |
| return this | |
| start: (block) -> | |
| return this if @running | |
| @start = AnimationBlock.getTime() - @elapsed | |
| @running = yes | |
| @responder?.animationStarted? this if @elapsed is 0 | |
| block ?= @block || Animation.animationBlock | |
| block.addAnimation this | |
| @block = block | |
| return this | |
| restart: (block) -> | |
| block ?= this.block || Animation.animationBlock | |
| @reset().start(block) | |
| tick: (time) -> | |
| if responder | |
| time ?= @start + @elapsed | |
| progress = @progress(time) | |
| if @responder? and progress < 1.0 | |
| easedProgress = if @timingFunc? then @timingFunc(progress) else progress | |
| @responder.animationFrame this, easedProgress | |
| if @running and progress >= 1 | |
| @stop() | |
| @responder?.animationFinished this | |
| anim.restart() for anim in @chain | |
| return this | |
| progress: (time) -> | |
| return 1.0 if not @running and @duration <= @elapsed | |
| time = if time? then time - @start else @elapsed | |
| return Math.min(1, Math.max(0, time * @durationOverOne)) | |
| reset: -> | |
| @elapsed = 0 | |
| return this | |
| isRunning: -> | |
| return @running | |
| chainAnimation: (anim) -> | |
| @chian.push anim | |
| return this | |
| setChain: (chain) -> | |
| if typeof chain isnt 'Array' | |
| return undefined | |
| @chain = chain.slice(0) | |
| return this | |
| @SHORT_DURATION = 120 | |
| @NORMAL_DURATION = 200 | |
| @LONG_DURATION = 320 | |
| @TIMING = | |
| linear: -> null | |
| easeInOut: (-> | |
| easingTable = [] | |
| for index in [0 .. 999] | |
| delta = index * 0.001 | |
| delta = (Math.sin((delta * Math.PI) - (Math.PI * 0.5)) * 0.5) + 0.5 | |
| easingTable[index] = Math.min(1.0, Math.max(0.0, delta)) | |
| return -> | |
| return (progress) -> | |
| easingTable[ Math.floor(progress * (easingTable.length - 1)) ] | |
| )() | |
| easeIn: (-> | |
| easingTable = [] | |
| for index in [0 .. 999] | |
| delta = index * 0.001 | |
| delta = Math.sin(Math.PI * 0.5 + delta * (Math.PI * 0.5)) | |
| easingTable[index] = 1.0 - Math.min(1.0, Math.max(0.0, delta)) | |
| return -> | |
| return (progress) -> | |
| easingTable[ Math.floor(progress * (easingTable.length - 1)) ] | |
| )() | |
| easeOut: (-> | |
| easingTable = [] | |
| for index in [0 .. 999] | |
| delta = index * 0.001 | |
| delta = Math.sin(delta * (Math.PI * 0.5)) | |
| easingTable[index] = Math.min(1.0, Math.max(0.0, delta)) | |
| return -> | |
| return (progress) -> | |
| easingTable[ Math.floor(progress * (easingTable.length - 1)) ] | |
| )() | |
| bounce: (bounceDelta, bounces, bounceScale, originalEasing) -> | |
| bounceDelta ?= 0.25 | |
| bounces ?= 3 | |
| bounceScale ?= 0.1 | |
| easingTable = [] | |
| deltaLength = Math.floor bounceDelta * 1000 | |
| insertLength = 1000 - deltaLength | |
| for index in [0 .. insertLength - 1] | |
| delta = index / insertLength | |
| easingTable[index] = if originalEasing? then originalEasing(delta) else delta | |
| offset = insertLength | |
| for bounce in [bounces .. 1] | |
| for index in [0 .. deltaLength - 1] | |
| bounceIndex = offset + index | |
| bounceDelta = Math.sin((index / deltaLength) * Math.PI) * bounceScale | |
| easingTable[bounceIndex] = 1.0 - bounceDelta | |
| bounceScale *= 0.25 | |
| offset += deltaLength | |
| return (progress) -> | |
| easingTable[ Math.floor(progress * (easingTable.length - 1)) ] |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment