-
Notifications
You must be signed in to change notification settings - Fork 479
/
Curves.coffee
133 lines (116 loc) · 4.17 KB
/
Curves.coffee
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
{BezierCurveAnimator} = require "./BezierCurveAnimator"
{computeDerivedCurveOptions, computeDuration, computeDampingRatio} = require "./SpringCurveValueConverter"
{SpringRK4Animator} = require "./SpringRK4Animator"
{Defaults} = require "../Defaults"
Bezier = (values...) ->
(options = {}) ->
options.values = values
new BezierCurveAnimator(options)
# We define each in a seperate function here
# so they become named functions
# and Framer.Curves.Bezier.ease.name is set
BezierDefaults =
linear: (options = {}) -> Bezier(0, 0, 1, 1)(options)
ease: (options = {}) -> Bezier(.25, .1, .25, 1)(options)
easeIn: (options = {}) -> Bezier(.42, 0, 1, 1)(options)
easeOut: (options = {}) -> Bezier(0, 0, .58, 1)(options)
easeInOut: (options = {}) -> Bezier(.42, 0, .58, 1)(options)
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