Instantly share code, notes, and snippets.

# gre/easing.js

Last active August 10, 2024 20:59
Show Gist options
• Save gre/1650294 to your computer and use it in GitHub Desktop.
Simple Easing Functions in Javascript - see https://github.com/gre/bezier-easing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
 /* * This work is free. You can redistribute it and/or modify it under the * terms of the Do What The Fuck You Want To Public License, Version 2, * as published by Sam Hocevar. See the COPYING file for more details. */ /* * Easing Functions - inspired from http://gizma.com/easing/ * only considering the t value for the range [0, 1] => [0, 1] */ EasingFunctions = { // no easing, no acceleration linear: t => t, // accelerating from zero velocity easeInQuad: t => t*t, // decelerating to zero velocity easeOutQuad: t => t*(2-t), // acceleration until halfway, then deceleration easeInOutQuad: t => t<.5 ? 2*t*t : -1+(4-2*t)*t, // accelerating from zero velocity easeInCubic: t => t*t*t, // decelerating to zero velocity easeOutCubic: t => (--t)*t*t+1, // acceleration until halfway, then deceleration easeInOutCubic: t => t<.5 ? 4*t*t*t : (t-1)*(2*t-2)*(2*t-2)+1, // accelerating from zero velocity easeInQuart: t => t*t*t*t, // decelerating to zero velocity easeOutQuart: t => 1-(--t)*t*t*t, // acceleration until halfway, then deceleration easeInOutQuart: t => t<.5 ? 8*t*t*t*t : 1-8*(--t)*t*t*t, // accelerating from zero velocity easeInQuint: t => t*t*t*t*t, // decelerating to zero velocity easeOutQuint: t => 1+(--t)*t*t*t*t, // acceleration until halfway, then deceleration easeInOutQuint: t => t<.5 ? 16*t*t*t*t*t : 1+16*(--t)*t*t*t*t }

### MisterSirCode commented Jan 17, 2020

Tip, you should convert them to arrow expressions, and dont minify, this is 2020, we dont need minification :D

ALSO you seemed to forget the "var" part of the EasingFunctions variable.

```var EasingFunctions = {
// no easing, no acceleration
linear: t => {
return t;
},
// accelerating from zero velocity
return t * t;
},
// decelerating to zero velocity
return t * (2 - t);
},
// acceleration until halfway, then deceleration
return t < 0.5 ? 2 * t * t : -1 + (4 - 2 * t) * t;
},
// accelerating from zero velocity
easeInCubic: t => {
return t * t * t;
},
// decelerating to zero velocity
easeOutCubic: t => {
return --t * t * t + 1;
},
// acceleration until halfway, then deceleration
easeInOutCubic: t => {
return t < 0.5 ? 4 * t * t * t : (t - 1) * (2 * t - 2) * (2 * t - 2) + 1;
},
// accelerating from zero velocity
easeInQuart: t => {
return t * t * t * t;
},
// decelerating to zero velocity
easeOutQuart: t => {
return 1 - --t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuart: t => {
return t < 0.5 ? 8 * t * t * t * t : 1 - 8 * --t * t * t * t;
},
// accelerating from zero velocity
easeInQuint: t => {
return t * t * t * t * t;
},
// decelerating to zero velocity
easeOutQuint: t => {
return 1 + --t * t * t * t * t;
},
// acceleration until halfway, then deceleration
easeInOutQuint: t => {
return t < 0.5 ? 16 * t * t * t * t * t : 1 + 16 * --t * t * t * t * t;
}
};```

@skylerspark done! it's a snippet, up to you to `var` it or `const` it or `module.exports=` it or `export default` it ;)

### mhaidarhanif commented Feb 23, 2020

@gre Very useful! Thank you very much, Gaëtan!

### temm1210 commented Jul 29, 2020

really awesome and useful!! Thank you!!

Great gist @gre!

I thought it might be helpful to those who wanted to extend the curves to see how that could be done using higher order functions and increasing the power (Thanks to @lindell for the original snippet! This version however removes the unnecessary `Math.abs`, reuses `easeIn` for the `easeOut` function and changes `linear` to reference `easeIn` rather than `easeInOut` to reduce the complexity for each call (although this definitely isn't an exercise in performance))

```const easeIn = p => t => Math.pow(t, p)
const easeOut = p => t => 1 - easeIn(p)(1 - t)
const easeInOut = p => t => t < .5 ? easeIn(p)(t * 2) / 2 : easeOut(p)(t * 2 - 1) / 2 + .5
const Easings = {
linear: easeIn(1),
easeInCubic: easeIn(3),
easeOutCubic: easeOut(3),
easeInOutCubic: easeInOut(3),
easeInQuart: easeIn(4),
easeOutQuart: easeOut(4),
easeInOutQuart: easeInOut(4),
easeInQuint: easeIn(5),
easeOutQuint: easeOut(5),
easeInOutQuint: easeInOut(5)
}```

Knowing this, you can re-write @gre's gist like so:

```const Easings = {
linear = t => t,
easeInQuad = t => Math.pow(t, 2),
easeOutQuad = t => 1 - Math.pow(1 - t, 2),
easeInOutQuad = t => t < .5 ? Math.pow(t * 2, 2) / 2 : (1 - Math.pow(1 - (t * 2 - 1), 2)) / 2 + .5,
easeInCubic = t => Math.pow(t, 3),
easeOutCubic = t => 1 - Math.pow(1 - t, 3),
easeInOutCubic = t => t < .5 ? Math.pow(t * 2, 3) / 2 : (1 - Math.pow(1 - (t * 2 - 1), 3)) / 2 + .5,
easeInQuart = t => Math.pow(t, 4),
easeOutQuart = t => 1 - Math.pow(1 - t, 4),
easeInOutQuart = t => t < .5 ? Math.pow(t * 2, 4) / 2 : (1 - Math.pow(1 - (t * 2 - 1), 4)) / 2 + .5,
easeInQuint = t => Math.pow(t, 5),
easeOutQuint = t => 1 - Math.pow(1 - t, 5),
easeInOutQuint = t => t < .5 ? Math.pow(t * 2, 5) / 2 : (1 - Math.pow(1 - (t * 2 - 1), 5)) / 2 + .5
}```

Although it is much more verbose, hopefully it's easier to understand for those who don't understand the pre-decrement tricks

Finally you can take the previous example and substitute parts of the equations to reference each other (cleaning it up a little bit)

```const linear = t => t
const easeInQuad = t => Math.pow(t, 2)
const easeInOutQuad = t => t < .5 ? easeInQuad(t * 2) / 2 : easeOutQuad(t * 2 - 1) / 2 + .5
const easeInCubic = t => Math.pow(t, 3)
const easeOutCubic = t => 1 - easeInCubic(1 - t)
const easeInOutCubic = t => t < .5 ? easeInCubic(t * 2) / 2 : easeOutCubic(t * 2 - 1) / 2 + .5
const easeInQuart = t => Math.pow(t, 4)
const easeOutQuart = t => 1 - easeInQuart(1 - t)
const easeInOutQuart = t => t < .5 ? easeInQuart(t * 2) / 2 : easeOutQuart(t * 2 - 1) / 2 + .5
const easeInQuint = t => Math.pow(t, 5)
const easeOutQuint = t => 1 - easeInQuint(1 - t)
const easeInOutQuint = t => t < .5 ? easeInQuint(t * 2) / 2 : easeOutQuint(t * 2 - 1) / 2 + .5```

### gre commented Apr 20, 2021

@aarongeorge thanks a lot! this is super useful! specifically, recently I was wondering how to generate it to any pow, I used this to something unrelated to easing but to do "distribution" => https://greweb.me/plots/109 (making my lines reaching more the edges)

### aarongeorge commented Apr 21, 2021

@gre glad I could return the favour! Full credit to @lindell for the original Higher Order implementation. I just wanted to break it down and tweak a few things so it benefits more people.

### ghost commented Nov 24, 2021

An alternative (works somehow)

`eval(function(p,a,c,k,e,d){e=function(c){return c.toString(36)};if(!''.replace(/^/,String)){while(c--){d[c.toString(a)]=k[c]||c.toString(a)}k=[function(e){return d[e]}];e=function(){return'\\w+'};c=1};while(c--){if(k[c]){p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c])}}return p}('f d={c:3(n){0 n},g:3(n){0 n*n},a:3(n){0 n*(2-n)},7:3(n){0 n<.5?2*n*n:(4-2*n)*n-1},9:3(n){0 n*n*n},b:3(n){0--n*n*n+1},e:3(n){0 n<.5?4*n*n*n:(n-1)*(2*n-2)*(2*n-2)+1},k:3(n){0 n*n*n*n},h:3(n){0 1- --n*n*n*n},i:3(n){0 n<.5?8*n*n*n*n:1-8*--n*n*n*n},l:3(n){0 n*n*n*n*n},j:3(n){0 1+--n*n*n*n*n},m:3(n){0 n<.5?6*n*n*n*n*n:1+6*--n*n*n*n*n}};',24,24,'return|||function|||16|easeInOutQuad||easeInCubic|easeOutQuad|easeOutCubic|linear|EasingFunctions|easeInOutCubic|var|easeInQuad|easeOutQuart|easeInOutQuart|easeOutQuint|easeInQuart|easeInQuint|easeInOutQuint|'.split('|'),0,{}))`

### nukadelic commented Jun 22, 2022

visual cheat sheet https://easings.net/

### phil-green-CTI commented Feb 28, 2023

This is really good but the easing functions are causing me trouble. I would like the first 75% of the count to go very quickly, and then decelerate to a crawl. I what would the proper function be for this? I imagine something like:

`const easeOut = t<.75 ? t => t : [SOMETHING] ;`

but I don't know what to put there.