aboutsummaryrefslogtreecommitdiffstats
path: root/src/_easing.scss
diff options
context:
space:
mode:
Diffstat (limited to 'src/_easing.scss')
-rw-r--r--src/_easing.scss483
1 files changed, 483 insertions, 0 deletions
diff --git a/src/_easing.scss b/src/_easing.scss
new file mode 100644
index 0000000..c41635b
--- /dev/null
+++ b/src/_easing.scss
@@ -0,0 +1,483 @@
1////
2/// Easing.
3///
4/// A collection of easing functions which are commonly used for animations.
5/// This code is based on https://github.com/gre/bezier-easing.
6///
7/// @group Easing
8///
9/// @access public
10////
11
12///
13/// @access private
14///
15$iro-cubic-bezier-sample-pool: ();
16
17///
18/// Sample pool size for cubic bezier calculations.
19///
20$iro-cubic-bezier-sample-pool-size: 10 !default;
21
22///
23/// Minimum slope required to use the Newton-Raphson method for cubic bezier calculations.
24///
25$iro-cubic-bezier-newton-min-slope: 0.001 !default;
26
27///
28/// Number of iterations of the Newton-Raphson method.
29///
30$iro-cubic-bezier-newton-iters: 4 !default;
31
32///
33/// Precision of the subdivision method for cubic bezier calculations.
34///
35$iro-cubic-bezier-subdiv-precision: 0.0000001 !default;
36
37///
38/// Maximum iterations of the subdivision method for cubic bezier calculations.
39///
40$iro-cubic-bezier-subdiv-max-iters: 10 !default;
41
42///
43/// A cubic bezier function identical to the CSS cubic-bezier function.
44///
45/// @param {number} $x1 - X of first point
46/// @param {number} $y1 - Y of first point
47/// @param {number} $x2 - X of second point
48/// @param {number} $y2 - Y of second point
49/// @param {number} $x - Progress between 0 and 1 inclusive
50///
51/// @return {number}
52///
53@function iro-cubic-bezier($x1, $y1, $x2, $y2, $x) {
54 //
55 // Cover simple cases
56 //
57
58 @if ($x1 == $y1) and ($x2 == $y2) {
59 @return $x;
60 }
61 @if $x == 0 {
62 @return 0;
63 }
64 @if $x == 1 {
65 @return 1;
66 }
67
68 //
69 // Generate samples
70 //
71
72 $sample-pool-key: $x1 + '_' + $x2;
73
74 @if not map-has-key($iro-cubic-bezier-sample-pool, $sample-pool-key) {
75 $samples: ();
76
77 @for $i from 0 through $iro-cubic-bezier-sample-pool-size {
78 $samples: append($samples, iro-cubic-bezier-func($x1, $x2, $i / $iro-cubic-bezier-sample-pool-size));
79 }
80
81 $iro-cubic-bezier-sample-pool: map-merge($iro-cubic-bezier-sample-pool, ($sample-pool-key: $samples)) !global;
82 }
83
84 //
85 // Calculate cubic bezier
86 //
87
88 @return iro-cubic-bezier-func($y1, $y2, iro-cubic-bezier-t-for-x($x1, $x2, $x));
89}
90
91///
92/// @access private
93///
94@function iro-cubic-bezier-func-a($p1, $p2) {
95 @return 1 - 3 * $p2 + 3 * $p1;
96}
97
98///
99/// @access private
100///
101@function iro-cubic-bezier-func-b($p1, $p2) {
102 @return 3 * $p2 - 6 * $p1;
103}
104
105///
106/// @access private
107///
108@function iro-cubic-bezier-func-c($p1) {
109 @return 3 * $p1;
110}
111
112///
113/// One-dimensional cubic bezier function.
114///
115/// @access private
116///
117@function iro-cubic-bezier-func($p1, $p2, $t) {
118 @return ((iro-cubic-bezier-func-a($p1, $p2) * $t + iro-cubic-bezier-func-b($p1, $p2)) * $t + iro-cubic-bezier-func-c($p1)) * $t;
119}
120
121///
122/// Derivative of the one-dimensional cubic bezier function.
123///
124/// @access private
125///
126@function iro-cubic-bezier-func-slope($p1, $p2, $t) {
127 @return 3 * iro-cubic-bezier-func-a($p1, $p2) * $t * $t + 2 * iro-cubic-bezier-func-b($p1, $p2) * $t + iro-cubic-bezier-func-c($p1);
128}
129
130///
131/// Newton-Raphson method to calculate the t parameter for a given x parameter.
132///
133/// @access private
134///
135@function iro-cubic-bezier-newton-raphson($x1, $x2, $x, $t) {
136 @for $i from 1 through $iro-cubic-bezier-newton-iters {
137 $cur-slope: iro-cubic-bezier-func-slope($x1, $x2, $t);
138
139 @if $cur-slope == 0 {
140 @return $t;
141 }
142
143 $cur-x: iro-cubic-bezier-func($x1, $x2, $t) - $x;
144 $t: $t - $cur-x / $cur-slope;
145 }
146
147 @return $t;
148}
149
150///
151/// Subdivision method to calculate the t parameter for a given x parameter.
152///
153/// @access private
154///
155@function iro-cubic-bezier-binary-subdivide($x1, $x2, $x, $a, $b) {
156 $cur-x: 0;
157 $cur-t: 0;
158 $i: 0;
159
160 @while $i < $iro-cubic-bezier-subdiv-max-iters {
161 $cur-t: $a + ($b - $a) / 2;
162 $cur-x: iro-cubic-bezier-func($x1, $x2, $cur-t) - $x;
163
164 @if $cur-x > 0 {
165 $b: $cur-t;
166 } @else {
167 $a: $cur-t;
168 }
169
170 @if abs($cur-x) < $iro-cubic-bezier-subdiv-precision {
171 @return $cur-t;
172 }
173 }
174
175 @return $cur-t;
176}
177
178///
179/// Calculate the t parameter for a given x parameter.
180///
181/// @access private
182///
183@function iro-cubic-bezier-t-for-x($x1, $x2, $x) {
184 $sample-pool-key: $x1 + '_' + $x2;
185 $samples: map-get($iro-cubic-bezier-sample-pool, $sample-pool-key);
186
187 $intv-start: 0;
188 $cur-sample: 1;
189 $last-sample: $iro-cubic-bezier-sample-pool-size;
190
191 @while ($cur-sample != $last-sample) and (nth($samples, $cur-sample) <= $x) {
192 $intv-start: $intv-start + (1 / $iro-cubic-bezier-sample-pool-size);
193 $cur-sample: $cur-sample + 1;
194 }
195 $cur-sample: $cur-sample - 1;
196
197 $dist: ($x - nth($samples, $cur-sample)) / (nth($samples, $cur-sample + 1) - nth($samples, $cur-sample));
198 $guess-t: $intv-start + $dist / $iro-cubic-bezier-sample-pool-size;
199
200 $init-slope: iro-cubic-bezier-func-slope($x1, $x2, $guess-t);
201 @if $init-slope >= $iro-cubic-bezier-newton-min-slope {
202 @return iro-cubic-bezier-newton-raphson($x1, $x2, $x, $guess-t);
203 } @else if $init-slope == 0 {
204 @return $guess-t;
205 } @else {
206 @return iro-cubic-bezier-binary-subdivide($x1, $x2, $x, $intv-start, $intv-start + 1 / $iro-cubic-bezier-sample-pool-size);
207 }
208}
209
210///
211/// Sinusoidal easing function (in direction).
212///
213/// @param {number} $x - Progress between 0 and 1 inclusive
214///
215/// @return {number}
216///
217@function iro-ease($x) {
218 @return iro-cubic-bezier(0.25, 0.1, 0.25, 1, $x);
219}
220
221///
222/// Sinusoidal easing function (in direction).
223///
224/// @param {number} $x - Progress between 0 and 1 inclusive
225///
226/// @return {number}
227///
228@function iro-ease-in($x) {
229 @return iro-cubic-bezier(0.42, 0, 1, 1, $x);
230}
231
232///
233/// Sinusoidal easing function (out direction).
234///
235/// @param {number} $x - Progress between 0 and 1 inclusive
236///
237/// @return {number}
238///
239@function iro-ease-out($x) {
240 @return iro-cubic-bezier(0, 0, 0.58, 1, $x);
241}
242
243///
244/// Sinusoidal easing function (in-out direction).
245///
246/// @param {number} $x - Progress between 0 and 1 inclusive
247///
248/// @return {number}
249///
250@function iro-ease-in-out($x) {
251 @return iro-cubic-bezier(0.42, 0, 0.58, 1, $x);
252}
253
254///
255/// Sinusoidal easing function (in direction).
256///
257/// @param {number} $x - Progress between 0 and 1 inclusive
258///
259/// @return {number}
260///
261@function iro-ease-in-sine($x) {
262 @return iro-cubic-bezier(0.47, 0, 0.745, 0.715, $x);
263}
264
265///
266/// Sinusoidal easing function (out direction).
267///
268/// @param {number} $x - Progress between 0 and 1 inclusive
269///
270/// @return {number}
271///
272@function iro-ease-out-sine($x) {
273 @return iro-cubic-bezier(0.39, 0.575, 0.565, 1, $x);
274}
275
276///
277/// Sinusoidal easing function (in-out direction).
278///
279/// @param {number} $x - Progress between 0 and 1 inclusive
280///
281/// @return {number}
282///
283@function iro-ease-in-out-sine($x) {
284 @return iro-cubic-bezier(0.445, 0.05, 0.55, 0.95, $x);
285}
286
287///
288/// Quadratic easing function (in direction).
289///
290/// @param {number} $x - Progress between 0 and 1 inclusive
291///
292/// @return {number}
293///
294@function iro-ease-in-quad($x) {
295 @return iro-cubic-bezier(0.55, 0.085, 0.68, 0.53, $x);
296}
297
298///
299/// Quadratic easing function (out direction).
300///
301/// @param {number} $x - Progress between 0 and 1 inclusive
302///
303/// @return {number}
304///
305@function iro-ease-out-quad($x) {
306 @return iro-cubic-bezier(0.25, 0.46, 0.45, 0.94, $x);
307}
308
309///
310/// Quadratic easing function (in-out direction).
311///
312/// @param {number} $x - Progress between 0 and 1 inclusive
313///
314/// @return {number}
315///
316@function iro-ease-in-out-quad($x) {
317 @return iro-cubic-bezier(0.455, 0.03, 0.515, 0.955, $x);
318}
319
320///
321/// Cubic easing function (in direction).
322///
323/// @param {number} $x - Progress between 0 and 1 inclusive
324///
325/// @return {number}
326///
327@function iro-ease-in-cubic($x) {
328 @return iro-cubic-bezier(0.55, 0.055, 0.675, 0.19, $x);
329}
330
331///
332/// Cubic easing function (out direction).
333///
334/// @param {number} $x - Progress between 0 and 1 inclusive
335///
336/// @return {number}
337///
338@function iro-ease-out-cubic($x) {
339 @return iro-cubic-bezier(0.215, 0.61, 0.355, 1, $x);
340}
341
342///
343/// Cubic easing function (in-out direction).
344///
345/// @param {number} $x - Progress between 0 and 1 inclusive
346///
347/// @return {number}
348///
349@function iro-ease-in-out-cubic($x) {
350 @return iro-cubic-bezier(0.645, 0.045, 0.355, 1, $x);
351}
352
353///
354/// Quart easing function (in direction).
355///
356/// @param {number} $x - Progress between 0 and 1 inclusive
357///
358/// @return {number}
359///
360@function iro-ease-in-quart($x) {
361 @return iro-cubic-bezier(0.895, 0.03, 0.685, 0.22, $x);
362}
363
364///
365/// Quart easing function (out direction).
366///
367/// @param {number} $x - Progress between 0 and 1 inclusive
368///
369/// @return {number}
370///
371@function iro-ease-out-quart($x) {
372 @return iro-cubic-bezier(0.165, 0.84, 0.44, 1, $x);
373}
374
375///
376/// Quart easing function (in-out direction).
377///
378/// @param {number} $x - Progress between 0 and 1 inclusive
379///
380/// @return {number}
381///
382@function iro-ease-in-out-quart($x) {
383 @return iro-cubic-bezier(0.77, 0, 0.175, 1, $x);
384}
385
386///
387/// Quint easing function (in direction).
388///
389/// @param {number} $x - Progress between 0 and 1 inclusive
390///
391/// @return {number}
392///
393@function iro-ease-in-quint($x) {
394 @return iro-cubic-bezier(0.755, 0.05, 0.855, 0.06, $x);
395}
396
397///
398/// Quint easing function (out direction).
399///
400/// @param {number} $x - Progress between 0 and 1 inclusive
401///
402/// @return {number}
403///
404@function iro-ease-out-quint($x) {
405 @return iro-cubic-bezier(0.23, 1, 0.32, 1, $x);
406}
407
408///
409/// Quint easing function (in-out direction).
410///
411/// @param {number} $x - Progress between 0 and 1 inclusive
412///
413/// @return {number}
414///
415@function iro-ease-in-out-quint($x) {
416 @return iro-cubic-bezier(0.86, 0, 0.07, 1, $x);
417}
418
419///
420/// Exponential easing function (in direction).
421///
422/// @param {number} $x - Progress between 0 and 1 inclusive
423///
424/// @return {number}
425///
426@function iro-ease-in-expo($x) {
427 @return iro-cubic-bezier(0.95, 0.05, 0.795, 0.035, $x);
428}
429
430///
431/// Exponential easing function (out direction).
432///
433/// @param {number} $x - Progress between 0 and 1 inclusive
434///
435/// @return {number}
436///
437@function iro-ease-out-expo($x) {
438 @return iro-cubic-bezier(0.19, 1, 0.22, 1, $x);
439}
440
441///
442/// Exponential easing function (in-out direction).
443///
444/// @param {number} $x - Progress between 0 and 1 inclusive
445///
446/// @return {number}
447///
448@function iro-ease-in-out-expo($x) {
449 @return iro-cubic-bezier(1, 0, 0, 1, $x);
450}
451
452///
453/// Circular easing function (in direction).
454///
455/// @param {number} $x - Progress between 0 and 1 inclusive
456///
457/// @return {number}
458///
459@function iro-ease-in-circ($x) {
460 @return iro-cubic-bezier(0.6, 0.04, 0.98, 0.335, $x);
461}
462
463///
464/// Circular easing function (out direction).
465///
466/// @param {number} $x - Progress between 0 and 1 inclusive
467///
468/// @return {number}
469///
470@function iro-ease-out-circ($x) {
471 @return iro-cubic-bezier(0.075, 0.82, 0.165, 1, $x);
472}
473
474///
475/// Circular easing function (in-out direction).
476///
477/// @param {number} $x - Progress between 0 and 1 inclusive
478///
479/// @return {number}
480///
481@function iro-ease-in-out-circ($x) {
482 @return iro-cubic-bezier(0.785, 0.135, 0.15, 0.86, $x);
483}