index.js
function animate(source, target, options) {
  var start = Object.create(null)
  var diff = Object.create(null)
  options = options || {}
  // We let clients specify their own easing function
  var easing = (typeof options.easing === 'function') ? options.easing : animations[options.easing]

  // if nothing is specified, default to ease (similar to CSS animations)
  if (!easing) {
    if (options.easing) {
      console.warn('Unknown easing function in amator: ' + options.easing);
    }
    easing = animations.ease
  }

  var step = typeof options.step === 'function' ? options.step : noop
  var done = typeof options.done === 'function' ? options.done : noop

  var scheduler = getScheduler(options.scheduler)

  var keys = Object.keys(target)
  keys.forEach(function(key) {
    start[key] = source[key]
    diff[key] = target[key] - source[key]
  })

  var durationInMs = typeof options.duration === 'number' ? options.duration : 400
  var durationInFrames = Math.max(1, durationInMs * 0.06) // 0.06 because 60 frames pers 1,000 ms
  var previousAnimationId
  var frame = 0

  previousAnimationId = scheduler.next(loop)

  return {
    cancel: cancel
  }

  function cancel() {
    scheduler.cancel(previousAnimationId)
    previousAnimationId = 0
  }

  function loop() {
    var t = easing(frame/durationInFrames)
    frame += 1
    setValues(t)
    if (frame <= durationInFrames) {
      previousAnimationId = scheduler.next(loop)
      step(source)
    } else {
      previousAnimationId = 0
      setTimeout(function() { done(source) }, 0)
    }
  }

  function setValues(t) {
    keys.forEach(function(key) {
      source[key] = diff[key] * t + start[key]
    })
  }
}
function animate(source, target, options) {
  var start = Object.create(null)
  var diff = Object.create(null)
  options = options || {}
  // We let clients specify their own easing function
  var easing = (typeof options.easing === 'function') ? options.easing : animations[options.easing]

  // if nothing is specified, default to ease (similar to CSS animations)
  if (!easing) {
    if (options.easing) {
      console.warn('Unknown easing function in amator: ' + options.easing);
    }
    easing = animations.ease
  }

  var step = typeof options.step === 'function' ? options.step : noop
  var done = typeof options.done === 'function' ? options.done : noop

  var scheduler = getScheduler(options.scheduler)

  var keys = Object.keys(target)
  keys.forEach(function(key) {
    start[key] = source[key]
    diff[key] = target[key] - source[key]
  })

  var durationInMs = typeof options.duration === 'number' ? options.duration : 400
  var durationInFrames = Math.max(1, durationInMs * 0.06) // 0.06 because 60 frames pers 1,000 ms
  var previousAnimationId
  var frame = 0

  previousAnimationId = scheduler.next(loop)

  return {
    cancel: cancel
  }

  function cancel() {
    scheduler.cancel(previousAnimationId)
    previousAnimationId = 0
  }

  function loop() {
    var t = easing(frame/durationInFrames)
    frame += 1
    setValues(t)
    if (frame <= durationInFrames) {
      previousAnimationId = scheduler.next(loop)
      step(source)
    } else {
      previousAnimationId = 0
      setTimeout(function() { done(source) }, 0)
    }
  }

  function setValues(t) {
    keys.forEach(function(key) {
      source[key] = diff[key] * t + start[key]
    })
  }
}
function animate ( source , target , options ) { var start = Object . create ( null ) var diff = Object . create ( null ) options = options || { } // We let clients specify their own easing function var easing = ( typeof options . easing === 'function' ) ? options . easing : animations [ options . easing ] // if nothing is specified, default to ease (similar to CSS animations) if ( ! easing ) { if ( options . easing ) { console . warn ( 'Unknown easing function in amator: ' + options . easing ) ; } easing = animations . ease } var step = typeof options . step === 'function' ? options . step : noop var done = typeof options . done === 'function' ? options . done : noop var scheduler = getScheduler ( options . scheduler ) var keys = Object . keys ( target ) keys . forEach ( function ( key ) { start [ key ] = source [ key ] diff [ key ] = target [ key ] - source [ key ] } ) var durationInMs = typeof options . duration === 'number' ? options . duration : 400 var durationInFrames = Math . max ( 1 , durationInMs * 0.06 ) // 0.06 because 60 frames pers 1,000 ms var previousAnimationId var frame = 0 previousAnimationId = scheduler . next ( loop ) return { cancel : cancel } function cancel ( ) { scheduler . cancel ( previousAnimationId ) previousAnimationId = 0 } function loop ( ) { var t = easing ( frame / durationInFrames ) frame += 1 setValues ( t ) if ( frame <= durationInFrames ) { previousAnimationId = scheduler . next ( loop ) step ( source ) } else { previousAnimationId = 0 setTimeout ( function ( ) { done ( source ) } , 0 ) } } function setValues ( t ) { keys . forEach ( function ( key ) { source [ key ] = diff [ key ] * t + start [ key ] } ) } }
Creates a new instance of animator. Animator uses
interpolation function to change `source` object into
`target` object.

Note: this method mutates `source` object properties.

@param {Object} source
@param {Object} target
@param {Object} options - animation configuration
@param {Function} options.step - called on each animation step
@param {Function} options.easing - easing function, which takes one
argument `t` in range [0, 1], and returns corresponding interpolation
value.
@param {Function} options.done - called when animation is over
Creates a new instance of animator . Animator uses interpolation function to change source object into target object .