v2 / vlib / math / easing / easing.v
266 lines · 232 sloc · 6.9 KB · 547564579df34da8d6d522d212df78c3313d5ca9
Raw
1module easing
2
3// Easing functions specify the value of a property, given a level of completeness from 0.0 to 1.0 .
4// The names of the easing functions here, are based on the ones from https://easings.net/ and
5// https://nicmulvaney.com/easing .
6import math { cos, pow, sin, sqrt }
7
8const pi = math.pi
9const pi_half = pi / 2.0
10const pi_double = pi * 2.0
11const c1 = 1.70158
12const c2 = c1 * 1.525
13const c3 = c1 + 1.0
14const c4 = pi_double / 3.0
15const c5 = pi_double / 4.5
16const n1 = 7.5625
17const d1 = 2.75
18
19// EasingFN defines the common shape of an easing function, so that you can define your own, and pass them everywhere,
20// that expects easing.EasingFN . It is just a function that accepts a floating point number and returns one too.
21pub type EasingFN = fn (x f64) f64
22
23// linear just returns the parameter x, without changes .
24@[inline]
25pub fn linear(x f64) f64 {
26 return x
27}
28
29// in_sine returns the equivalent of https://easings.net/#easeInSine .
30@[inline]
31pub fn in_sine(x f64) f64 {
32 return 1.0 - cos(x * pi_half)
33}
34
35// out_sine returns the equivalent of https://easings.net/#easeOutSine .
36@[inline]
37pub fn out_sine(x f64) f64 {
38 return sin(x * pi_half)
39}
40
41// in_out_sine returns the equivalent of https://easings.net/#easeInOutSine .
42@[inline]
43pub fn in_out_sine(x f64) f64 {
44 return -(cos(pi * x) - 1.0) / 2.0
45}
46
47// in_quad returns the equivalent of https://easings.net/#easeInQuad .
48@[inline]
49pub fn in_quad(x f64) f64 {
50 return x * x
51}
52
53// out_quad returns the equivalent of https://easings.net/#easeOutQuad .
54@[inline]
55pub fn out_quad(x f64) f64 {
56 return 1.0 - (1.0 - x) * (1.0 - x)
57}
58
59// in_out_quad returns the equivalent of https://easings.net/#easeInOutQuad .
60@[inline]
61pub fn in_out_quad(x f64) f64 {
62 return if x < 0.5 { 2.0 * x * x } else { 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0 }
63}
64
65// in_cubic returns the equivalent of https://easings.net/#easeInCubic .
66@[inline]
67pub fn in_cubic(x f64) f64 {
68 return x * x * x
69}
70
71// out_cubic returns the equivalent of https://easings.net/#easeOutCubic .
72@[inline]
73pub fn out_cubic(x f64) f64 {
74 return 1.0 - (1.0 - x) * (1.0 - x) * (1.0 - x)
75}
76
77// in_out_cubic returns the equivalent of https://easings.net/#easeInOutCubic .
78@[inline]
79pub fn in_out_cubic(x f64) f64 {
80 return if x < .5 {
81 4.0 * x * x * x
82 } else {
83 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0
84 }
85}
86
87// in_quart returns the equivalent of https://easings.net/#easeInQuart .
88@[inline]
89pub fn in_quart(x f64) f64 {
90 return x * x * x * x
91}
92
93// out_quart returns the equivalent of https://easings.net/#easeOutQuart .
94@[inline]
95pub fn out_quart(x f64) f64 {
96 return 1.0 - (1.0 - x) * (1.0 - x) * (1.0 - x) * (1.0 - x)
97}
98
99// in_out_quart returns the equivalent of https://easings.net/#easeInOutQuart .
100@[inline]
101pub fn in_out_quart(x f64) f64 {
102 return if x < 0.5 {
103 8.0 * x * x * x * x
104 } else {
105 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0
106 }
107}
108
109// in_quint returns the equivalent of https://easings.net/#easeInQuint .
110@[inline]
111pub fn in_quint(x f64) f64 {
112 return x * x * x * x * x
113}
114
115// out_quint returns the equivalent of https://easings.net/#easeOutQuint .
116@[inline]
117pub fn out_quint(x f64) f64 {
118 return 1.0 - (1.0 - x) * (1.0 - x) * (1.0 - x) * (1.0 - x) * (1.0 - x)
119}
120
121// in_out_quint returns the equivalent of https://easings.net/#easeInOutQuint .
122@[inline]
123pub fn in_out_quint(x f64) f64 {
124 return if x < 0.5 {
125 16.0 * x * x * x * x * x
126 } else {
127 1.0 - (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) * (2.0 - 2.0 * x) / 2.0
128 }
129}
130
131// in_expo returns the equivalent of https://easings.net/#easeInExpo .
132@[inline]
133pub fn in_expo(x f64) f64 {
134 return if math.close(x, 0.0) { 0.0 } else { pow(2.0, 10.0 * x - 10.0) }
135}
136
137// out_expo returns the equivalent of https://easings.net/#easeOutExpo .
138@[inline]
139pub fn out_expo(x f64) f64 {
140 return if math.close(x, 1.0) { 1.0 } else { 1.0 - pow(2, -10.0 * x) }
141}
142
143// in_out_expo returns the equivalent of https://easings.net/#easeInOutExpo .
144@[inline]
145pub fn in_out_expo(x f64) f64 {
146 return if math.close(x, 0.0) {
147 0.0
148 } else if math.close(x, 1.0) {
149 1.0
150 } else if x < 0.5 {
151 pow(2.0, 20.0 * x - 10.0) / 2.0
152 } else {
153 (2.0 - pow(2.0, 10.0 - 20.0 * x)) / 2.0
154 }
155}
156
157// in_circ returns the equivalent of https://easings.net/#easeInCirc .
158@[inline]
159pub fn in_circ(x f64) f64 {
160 return 1.0 - sqrt(1.0 - x * x)
161}
162
163// out_circ returns the equivalent of https://easings.net/#easeOutCirc .
164@[inline]
165pub fn out_circ(x f64) f64 {
166 return sqrt(1.0 - pow(x - 1.0, 2.0))
167}
168
169// in_out_circ returns the equivalent of https://easings.net/#easeInOutCirc .
170@[inline]
171pub fn in_out_circ(x f64) f64 {
172 return if x < 0.5 {
173 (1.0 - sqrt(1.0 - pow(2.0 * x, 2.0))) / 2.0
174 } else {
175 (sqrt(1.0 - pow(-2.0 * x + 2.0, 2.0)) + 1.0) / 2.0
176 }
177}
178
179// in_back returns the equivalent of https://easings.net/#easeInBack .
180@[inline]
181pub fn in_back(x f64) f64 {
182 return c3 * x * x * x - c1 * x * x
183}
184
185// out_back returns the equivalent of https://easings.net/#easeOutBack .
186@[inline]
187pub fn out_back(x f64) f64 {
188 return 1.0 + c3 * pow(x - 1.0, 3.0) + c1 * pow(x - 1.0, 2.0)
189}
190
191// in_out_back returns the equivalent of https://easings.net/#easeInOutBack .
192@[inline]
193pub fn in_out_back(x f64) f64 {
194 return if x < 0.5 {
195 (pow(2.0 * x, 2.0) * ((c2 + 1) * 2.0 * x - c2)) / 2.0
196 } else {
197 (pow(2.0 * x - 2.0, 2.0) * ((c2 + 1.0) * (x * 2.0 - 2.0) + c2) + 2.0) / 2.0
198 }
199}
200
201// in_elastic returns the equivalent of https://easings.net/#easeInElastic .
202@[inline]
203pub fn in_elastic(x f64) f64 {
204 return if math.close(x, 0.0) {
205 0.0
206 } else if math.close(x, 1.0) {
207 1.0
208 } else {
209 -pow(2.0, 10.0 * x - 10.0) * sin((x * 10.0 - 10.75) * c4)
210 }
211}
212
213// out_elastic returns the equivalent of https://easings.net/#easeOutElastic .
214@[inline]
215pub fn out_elastic(x f64) f64 {
216 return if math.close(x, 0.0) {
217 0.0
218 } else if math.close(x, 1.0) {
219 1.0
220 } else {
221 pow(2.0, -10.0 * x) * sin((x * 10.0 - 0.75) * c4) + 1.0
222 }
223}
224
225// in_out_elastic returns the equivalent of https://easings.net/#easeInOutElastic .
226@[inline]
227pub fn in_out_elastic(x f64) f64 {
228 return if math.close(x, 0.0) {
229 0.0
230 } else if math.close(x, 1.0) {
231 1.0
232 } else if x < 0.5 {
233 -(pow(2.0, 20.0 * x - 10.0) * sin((20.0 * x - 11.125) * c5)) / 2.0
234 } else {
235 (pow(2.0, -20.0 * x + 10.0) * sin((20.0 * x - 11.125) * c5)) / 2.0 + 1.0
236 }
237}
238
239// in_bounce returns the equivalent of https://easings.net/#easeInBounce .
240@[inline]
241pub fn in_bounce(x f64) f64 {
242 return 1.0 - out_bounce(1.0 - x)
243}
244
245// out_bounce returns the equivalent of https://easings.net/#easeOutBounce .
246pub fn out_bounce(x f64) f64 {
247 xd1 := x * d1
248 return if xd1 < 1.0 {
249 n1 * x * x
250 } else if xd1 < 2.0 {
251 n1 * pow(x - 1.5 / d1, 2.0) + 0.75
252 } else if xd1 < 2.5 {
253 n1 * pow(x - 2.25 / d1, 2.0) + 0.9375
254 } else {
255 n1 * pow(x - 2.625 / d1, 2.0) + 0.984375
256 }
257}
258
259// in_out_bounce returns the equivalent of https://easings.net/#easeInOutBounce .
260pub fn in_out_bounce(x f64) f64 {
261 return if x < 0.5 {
262 (1.0 - out_bounce(1.0 - 2.0 * x)) / 2.0
263 } else {
264 (1.0 + out_bounce(2.0 * x - 1.0)) / 2.0
265 }
266}
267