Skip to content
Permalink
Browse files

Merge pull request #467 from koenbok/feature/spring-improvements

Feature/spring improvements
  • Loading branch information
nvh committed Feb 10, 2017
2 parents ad9fa7e + bf8b7d5 commit d50c3f8cd98e0324baeaeda873926d09c33434d3
@@ -5,8 +5,9 @@ Utils = require "./Utils"
{Config} = require "./Config"
{Defaults} = require "./Defaults"
{BaseClass} = require "./BaseClass"
{Animator} = require "./Animator"
{Animator} = require "./Animators/Animator"
{LinearAnimator} = require "./Animators/LinearAnimator"
Curves = require "./Animators/Curves"

numberRE = /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/
relativePropertyRE = new RegExp("^(?:([+-])=|)(" + numberRE.source + ")([a-z%]*)$", "i")
@@ -83,7 +84,10 @@ class exports.Animation extends BaseClass
if properties.origin
console.warn "Animation.origin: please use layer.originX and layer.originY"

@options.curveOptions = Animator.curveOptionsFor(@options)
if _.isString @options.curve
@options.curve = Curves.fromString(@options.curve)
if @options.curve is Curves.Spring
@options.curve = @options.curve.call()
@_originalState = @_currentState()
@_repeatCounter = @options.repeat

@@ -105,8 +109,7 @@ class exports.Animation extends BaseClass
@define "isNoop", @simpleProperty("isNoop", false)

start: =>

@_animator = Animation._createAnimator(@options) ? new LinearAnimator(@options.curveOptions)
@_animator = @options.curve(@options)
@_target = @layer
@_stateA = @_currentState()
@_stateB = {}
@@ -291,15 +294,6 @@ class exports.Animation extends BaseClass
_currentState: ->
return _.pick(@layer, _.keys(@properties))

@_createAnimator: (options) ->
AnimatorClass = Animator.classForCurve(options.curve)
return null if not AnimatorClass?
curveOptions = options.curveOptions ? Animator.curveOptionsFor(options)
if options.debug
console.log "Animation.start #{AnimatorClass.name}", curveOptions

return new AnimatorClass curveOptions

@isAnimatable = (v) ->
_.isNumber(v) or _.isFunction(v) or isRelativeProperty(v) or Color.isColorObject(v)

This file was deleted.

@@ -0,0 +1,27 @@
class exports.Animator

"""
The animator class is a very simple class that
- Takes a set of input values at setup({input values})
- Emits an output value for progress (0 -> 1) in value(progress)
"""

constructor: (options={}) ->
@setup options

setup: (options) ->
throw Error "Not implemented"

next: (delta) ->
throw Error "Not implemented"

finished: ->
throw Error "Not implemented"

values: (delta=1/60, limit=100) ->
values = []
for i in [0..limit]
values.push(@next(delta))
if @finished()
break
return values
@@ -1,4 +1,4 @@
{Animator} = require "../Animator"
{Animator} = require "./Animator"

BezierCurveDefaults =
"linear": [0, 0, 1, 1]
@@ -26,7 +26,7 @@ class exports.BezierCurveAnimator extends Animator
@options = _.defaults options,
values: BezierCurveDefaults["ease-in-out"]
time: 1
precision: 1/1000
precision: 1 / 1000

@_unitBezier = new UnitBezier \
@options.values[0],
@@ -0,0 +1,131 @@
{BezierCurveAnimator} = require "./BezierCurveAnimator"
{computeDerivedCurveOptions, computeDuration, computeDampingRatio} = require "./SpringCurveValueConverter"
{SpringRK4Animator} = require "./SpringRK4Animator"
{Defaults} = require "../Defaults"

Bezier = (values...) ->
(options = {}) ->
options.values = values
new BezierCurveAnimator(options)

BezierDefaults =
linear: Bezier(0, 0, 1, 1)
ease: Bezier(.25, .1, .25, 1)
easeIn: Bezier(.42, 0, 1, 1)
easeOut: Bezier(0, 0, .58, 1)
easeInOut: Bezier(.42, 0, .58, 1)


Spring = (dampingRatio, mass, velocity) ->
curveOptions = {}
if dampingRatio? and _.isFinite(dampingRatio)
curveOptions.dampingRatio = dampingRatio
if mass?
curveOptions.mass = mass
if velocity?
curveOptions.velocity = velocity
if not _.isFinite(dampingRatio) and typeof dampingRatio is 'object'
curveOptions = dampingRatio
if curveOptions.damping? and not curveOptions.dampingRatio?
curveOptions.dampingRatio = curveOptions.damping
if not curveOptions.tension? and not curveOptions.friction?
curveOptions = Defaults.getDefaults "Spring", curveOptions


return (options) ->
if curveOptions.dampingRatio?
duration = options?.time ? 1
derivedOptions = computeDerivedCurveOptions(curveOptions.dampingRatio, duration, curveOptions.velocity, curveOptions.mass)
curveOptions = _.defaults derivedOptions, curveOptions
else
delete options?.time
options = _.defaults curveOptions, options
animator = new SpringRK4Animator(options)
if duration?
animator.time = duration
animator

_.assign Bezier, BezierDefaults
Spring.computeDerivedCurveOptions = computeDerivedCurveOptions
Spring.computeDuration = computeDuration
Spring.computeDampingRatio = computeDampingRatio


exports.Spring = Spring
exports.Bezier = Bezier
parseFunction = (string) ->
return null unless _.isString string

# This parses functions with or without arguments like Bezier(0.1, 0.2, 0.3, 0.4) and Spring(damping: 0.5)
regex = /.*(Spring|Bezier)(?:\(\s*{?([\w:\s,.]*)}?\s*\)|\.(\w+))?/
matches = regex.exec(string)
return null unless matches?
[match, type, args, prop] = matches
result = {name: type, property: null, arguments: null}
if prop?
result.property = prop
return result
if not args?
return result
if args.length is 0
result.arguments = []


argumentsRegex = /\s*([\w]+)\s*:\s*([\d.]+)\s*,?/g
argumentObject = {}
while matches = argumentsRegex.exec(args)
[match, property, value] = matches
value = parseFloat(value)
if not isNaN(value)
argumentObject[property] = value
if _.size(argumentObject) > 0
result.arguments = argumentObject
return result

numbersRegex = /\s*([.\d]+)\s*/g
numbers = []
while matches = numbersRegex.exec(args)
[match, value] = matches
value = parseFloat(value)
numbers.push(value)
result.arguments = numbers
return result

fromDefinition = (definition) ->
return null unless definition?
curve = Framer.Curves[definition.name]
return null unless curve?

if definition.property?
return curve[definition.property]
if not definition.arguments?
return curve

if _.isArray(definition.arguments)
return curve(definition.arguments...)

return curve(definition.arguments)

exports.parseFunction = parseFunction
exports.fromDefinition = fromDefinition
exports.fromString = (string) ->
return null unless _.isString string
func = fromDefinition(parseFunction(string))
if func?
return func
func = Utils.parseFunction(string)
args = func.args.map(parseFloat)
switch func.name
when "linear" then Bezier.linear
when "ease" then Bezier.ease
when "ease-in" then Bezier.easeIn
when "ease-out" then Bezier.easeOut
when "ease-in-out" then Bezier.easeInOut
when "bezier-curve", "cubic-bezier"
Bezier(args...)
when "spring", "spring-rk4", "spring-dho"
pairs = _.zipWith(["tension", "friction", "velocity", "tolerance"], args, [250, 25, 0, 1 / 100], (key, value, defaults) -> [key, value ? defaults])
object = _.fromPairs(pairs)
Spring(object)
else
return Bezier.linear
@@ -1,12 +1,12 @@
{Animator} = require "../Animator"
{Animator} = require "./Animator"

class exports.LinearAnimator extends Animator

setup: (options) ->

@options = _.defaults options,
time: 1
precision: 1/1000
precision: 1 / 1000

@_time = 0

0 comments on commit d50c3f8

Please sign in to comment.
You can’t perform that action at this time.