neft
Version:
Universal Platform
134 lines (109 loc) • 3.81 kB
text/coffeescript
'use strict'
utils = require 'src/utils'
assert = require 'src/assert'
module.exports = (impl) ->
{Types} = impl
{now} = Date
{round} = Math
pending = []
nowTime = now()
vsync = ->
nowTime = now()
i = 0; n = pending.length
while i < n
anim = pending[i]
if anim._running and not anim._paused
updateAnimation anim
i++
else
# remove element in not ordered list
# this array may change due loop
pending[i] = pending[n-1]
pending[n-1] = pending[pending.length-1]
pending.pop()
anim._impl.pending = false
n--
requestAnimationFrame vsync
return
requestAnimationFrame? vsync
updateAnimation = (anim) ->
data = anim._impl
progress = (nowTime - data.startTime) / anim._duration
if progress < 0
data.progress = 0
return
else if progress > 1
progress = 1
data.progress = progress
running = progress isnt 1 or (anim._running and anim._loop and anim._when)
if progress is 1
val = data.to
else
val = data.easing anim._duration * progress, data.from, (data.to - data.from), anim._duration
target = anim._target
if val is val and target and (property = anim._property) # isNaN hack
if not running or anim._updateProperty or not data.propertySetter
anim._updatePending = true
target[property] = val
anim._updatePending = false
# force impl update, because setter won't update if nothing change in data
if progress is 1 and data.propertySetter and target[property] is val
impl[data.propertySetter].call target, val
else
impl[data.propertySetter].call target, val
if anim._updateData
target[data.internalPropertyName] = val
if progress is 1
if running
data.startTime += anim._loopDelay + anim._duration
else
data.startTime = 0
anim.running = false
return
DATA =
type: 'number'
pending: false
startTime: 0
pauseTime: 0
from: 0
to: 0
DATA: DATA
createData: impl.utils.createDataCloner 'PropertyAnimation', DATA
create: (data) ->
impl.Types.PropertyAnimation.create.call @, data
startAnimation: do (_super = impl.startAnimation) -> ->
_super.call @
if @_impl.type is 'number'
data = @_impl
data.from = @_from
data.to = @_to
unless data.pending
pending.push @
data.pending = true
data.startTime = nowTime
updateAnimation @
data.startTime += @_startDelay
return
stopAnimation: do (_super = impl.stopAnimation) -> ->
_super.call @
data = @_impl
if data.type is 'number' and data.startTime isnt 0
data.startTime = 0
updateAnimation @
return
resumeAnimation: do (_super = impl.resumeAnimation) -> ->
_super.call @
if @_impl.type is 'number'
data = @_impl
unless data.pending
pending.push @
data.pending = true
data.startTime += Date.now() - data.pauseTime
data.pauseTime = 0
return
pauseAnimation: do (_super = impl.pauseAnimation) -> ->
_super.call @
data = @_impl
if data.type is 'number'
data.pauseTime = Date.now()
return