From d07f664450ddaaebb44127a4bd057763d13d3f82 Mon Sep 17 00:00:00 2001 From: Feuerfuchs Date: Sun, 1 Nov 2020 20:55:14 +0100 Subject: Init --- src/_easing.scss | 483 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 483 insertions(+) create mode 100644 src/_easing.scss (limited to 'src/_easing.scss') 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 @@ +//// +/// Easing. +/// +/// A collection of easing functions which are commonly used for animations. +/// This code is based on https://github.com/gre/bezier-easing. +/// +/// @group Easing +/// +/// @access public +//// + +/// +/// @access private +/// +$iro-cubic-bezier-sample-pool: (); + +/// +/// Sample pool size for cubic bezier calculations. +/// +$iro-cubic-bezier-sample-pool-size: 10 !default; + +/// +/// Minimum slope required to use the Newton-Raphson method for cubic bezier calculations. +/// +$iro-cubic-bezier-newton-min-slope: 0.001 !default; + +/// +/// Number of iterations of the Newton-Raphson method. +/// +$iro-cubic-bezier-newton-iters: 4 !default; + +/// +/// Precision of the subdivision method for cubic bezier calculations. +/// +$iro-cubic-bezier-subdiv-precision: 0.0000001 !default; + +/// +/// Maximum iterations of the subdivision method for cubic bezier calculations. +/// +$iro-cubic-bezier-subdiv-max-iters: 10 !default; + +/// +/// A cubic bezier function identical to the CSS cubic-bezier function. +/// +/// @param {number} $x1 - X of first point +/// @param {number} $y1 - Y of first point +/// @param {number} $x2 - X of second point +/// @param {number} $y2 - Y of second point +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-cubic-bezier($x1, $y1, $x2, $y2, $x) { + // + // Cover simple cases + // + + @if ($x1 == $y1) and ($x2 == $y2) { + @return $x; + } + @if $x == 0 { + @return 0; + } + @if $x == 1 { + @return 1; + } + + // + // Generate samples + // + + $sample-pool-key: $x1 + '_' + $x2; + + @if not map-has-key($iro-cubic-bezier-sample-pool, $sample-pool-key) { + $samples: (); + + @for $i from 0 through $iro-cubic-bezier-sample-pool-size { + $samples: append($samples, iro-cubic-bezier-func($x1, $x2, $i / $iro-cubic-bezier-sample-pool-size)); + } + + $iro-cubic-bezier-sample-pool: map-merge($iro-cubic-bezier-sample-pool, ($sample-pool-key: $samples)) !global; + } + + // + // Calculate cubic bezier + // + + @return iro-cubic-bezier-func($y1, $y2, iro-cubic-bezier-t-for-x($x1, $x2, $x)); +} + +/// +/// @access private +/// +@function iro-cubic-bezier-func-a($p1, $p2) { + @return 1 - 3 * $p2 + 3 * $p1; +} + +/// +/// @access private +/// +@function iro-cubic-bezier-func-b($p1, $p2) { + @return 3 * $p2 - 6 * $p1; +} + +/// +/// @access private +/// +@function iro-cubic-bezier-func-c($p1) { + @return 3 * $p1; +} + +/// +/// One-dimensional cubic bezier function. +/// +/// @access private +/// +@function iro-cubic-bezier-func($p1, $p2, $t) { + @return ((iro-cubic-bezier-func-a($p1, $p2) * $t + iro-cubic-bezier-func-b($p1, $p2)) * $t + iro-cubic-bezier-func-c($p1)) * $t; +} + +/// +/// Derivative of the one-dimensional cubic bezier function. +/// +/// @access private +/// +@function iro-cubic-bezier-func-slope($p1, $p2, $t) { + @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); +} + +/// +/// Newton-Raphson method to calculate the t parameter for a given x parameter. +/// +/// @access private +/// +@function iro-cubic-bezier-newton-raphson($x1, $x2, $x, $t) { + @for $i from 1 through $iro-cubic-bezier-newton-iters { + $cur-slope: iro-cubic-bezier-func-slope($x1, $x2, $t); + + @if $cur-slope == 0 { + @return $t; + } + + $cur-x: iro-cubic-bezier-func($x1, $x2, $t) - $x; + $t: $t - $cur-x / $cur-slope; + } + + @return $t; +} + +/// +/// Subdivision method to calculate the t parameter for a given x parameter. +/// +/// @access private +/// +@function iro-cubic-bezier-binary-subdivide($x1, $x2, $x, $a, $b) { + $cur-x: 0; + $cur-t: 0; + $i: 0; + + @while $i < $iro-cubic-bezier-subdiv-max-iters { + $cur-t: $a + ($b - $a) / 2; + $cur-x: iro-cubic-bezier-func($x1, $x2, $cur-t) - $x; + + @if $cur-x > 0 { + $b: $cur-t; + } @else { + $a: $cur-t; + } + + @if abs($cur-x) < $iro-cubic-bezier-subdiv-precision { + @return $cur-t; + } + } + + @return $cur-t; +} + +/// +/// Calculate the t parameter for a given x parameter. +/// +/// @access private +/// +@function iro-cubic-bezier-t-for-x($x1, $x2, $x) { + $sample-pool-key: $x1 + '_' + $x2; + $samples: map-get($iro-cubic-bezier-sample-pool, $sample-pool-key); + + $intv-start: 0; + $cur-sample: 1; + $last-sample: $iro-cubic-bezier-sample-pool-size; + + @while ($cur-sample != $last-sample) and (nth($samples, $cur-sample) <= $x) { + $intv-start: $intv-start + (1 / $iro-cubic-bezier-sample-pool-size); + $cur-sample: $cur-sample + 1; + } + $cur-sample: $cur-sample - 1; + + $dist: ($x - nth($samples, $cur-sample)) / (nth($samples, $cur-sample + 1) - nth($samples, $cur-sample)); + $guess-t: $intv-start + $dist / $iro-cubic-bezier-sample-pool-size; + + $init-slope: iro-cubic-bezier-func-slope($x1, $x2, $guess-t); + @if $init-slope >= $iro-cubic-bezier-newton-min-slope { + @return iro-cubic-bezier-newton-raphson($x1, $x2, $x, $guess-t); + } @else if $init-slope == 0 { + @return $guess-t; + } @else { + @return iro-cubic-bezier-binary-subdivide($x1, $x2, $x, $intv-start, $intv-start + 1 / $iro-cubic-bezier-sample-pool-size); + } +} + +/// +/// Sinusoidal easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease($x) { + @return iro-cubic-bezier(0.25, 0.1, 0.25, 1, $x); +} + +/// +/// Sinusoidal easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in($x) { + @return iro-cubic-bezier(0.42, 0, 1, 1, $x); +} + +/// +/// Sinusoidal easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out($x) { + @return iro-cubic-bezier(0, 0, 0.58, 1, $x); +} + +/// +/// Sinusoidal easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out($x) { + @return iro-cubic-bezier(0.42, 0, 0.58, 1, $x); +} + +/// +/// Sinusoidal easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-sine($x) { + @return iro-cubic-bezier(0.47, 0, 0.745, 0.715, $x); +} + +/// +/// Sinusoidal easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-sine($x) { + @return iro-cubic-bezier(0.39, 0.575, 0.565, 1, $x); +} + +/// +/// Sinusoidal easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-sine($x) { + @return iro-cubic-bezier(0.445, 0.05, 0.55, 0.95, $x); +} + +/// +/// Quadratic easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-quad($x) { + @return iro-cubic-bezier(0.55, 0.085, 0.68, 0.53, $x); +} + +/// +/// Quadratic easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-quad($x) { + @return iro-cubic-bezier(0.25, 0.46, 0.45, 0.94, $x); +} + +/// +/// Quadratic easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-quad($x) { + @return iro-cubic-bezier(0.455, 0.03, 0.515, 0.955, $x); +} + +/// +/// Cubic easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-cubic($x) { + @return iro-cubic-bezier(0.55, 0.055, 0.675, 0.19, $x); +} + +/// +/// Cubic easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-cubic($x) { + @return iro-cubic-bezier(0.215, 0.61, 0.355, 1, $x); +} + +/// +/// Cubic easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-cubic($x) { + @return iro-cubic-bezier(0.645, 0.045, 0.355, 1, $x); +} + +/// +/// Quart easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-quart($x) { + @return iro-cubic-bezier(0.895, 0.03, 0.685, 0.22, $x); +} + +/// +/// Quart easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-quart($x) { + @return iro-cubic-bezier(0.165, 0.84, 0.44, 1, $x); +} + +/// +/// Quart easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-quart($x) { + @return iro-cubic-bezier(0.77, 0, 0.175, 1, $x); +} + +/// +/// Quint easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-quint($x) { + @return iro-cubic-bezier(0.755, 0.05, 0.855, 0.06, $x); +} + +/// +/// Quint easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-quint($x) { + @return iro-cubic-bezier(0.23, 1, 0.32, 1, $x); +} + +/// +/// Quint easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-quint($x) { + @return iro-cubic-bezier(0.86, 0, 0.07, 1, $x); +} + +/// +/// Exponential easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-expo($x) { + @return iro-cubic-bezier(0.95, 0.05, 0.795, 0.035, $x); +} + +/// +/// Exponential easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-expo($x) { + @return iro-cubic-bezier(0.19, 1, 0.22, 1, $x); +} + +/// +/// Exponential easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-expo($x) { + @return iro-cubic-bezier(1, 0, 0, 1, $x); +} + +/// +/// Circular easing function (in direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-circ($x) { + @return iro-cubic-bezier(0.6, 0.04, 0.98, 0.335, $x); +} + +/// +/// Circular easing function (out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-out-circ($x) { + @return iro-cubic-bezier(0.075, 0.82, 0.165, 1, $x); +} + +/// +/// Circular easing function (in-out direction). +/// +/// @param {number} $x - Progress between 0 and 1 inclusive +/// +/// @return {number} +/// +@function iro-ease-in-out-circ($x) { + @return iro-cubic-bezier(0.785, 0.135, 0.15, 0.86, $x); +} -- cgit v1.2.3-54-g00ecf