{"id":280294,"date":"2018-12-18T12:28:24","date_gmt":"2018-12-18T19:28:24","guid":{"rendered":"http:\/\/css-tricks.com\/?p=280294"},"modified":"2018-12-18T12:28:24","modified_gmt":"2018-12-18T19:28:24","slug":"ease-y-breezy-a-primer-on-easing-functions","status":"publish","type":"post","link":"https:\/\/css-tricks.com\/ease-y-breezy-a-primer-on-easing-functions\/","title":{"rendered":"Ease-y Breezy: A Primer on Easing Functions"},"content":{"rendered":"

During the past few months, I\u2019ve been actively teaching myself how to draw and animate SVG shapes. I\u2019ve been using CSS transitions, as well as tools like D3.js<\/a>, react-motion<\/a> and GSAP<\/a>, to create my animations.<\/p>\n

One thing about animations in general and the documentation these and other animation tools recommend is using easing functions<\/strong>. I\u2019ve been working with them in some capacity over the years, but to be honest, I would never know which function to choose for which kind of animation. Moreover, I did not know about the magic that goes into each of these functions, the notable differences between them, and how to use them effectively. But I was fine with that because I knew that easing functions somehow \u201csmoothed\u201d things out and mostly made my work look realistic.<\/p>\n

Here, I present to you what I learned about easing functions in the form of a primer that I hope gives you a good understanding as you dig into animations.<\/p>\n

<\/p>\n

How I got into easing functions<\/h3>\n

I tried to re-create a pattern called rotating snakes<\/a>, an optical illusion that tricks the brains into thinking that circles rotate and \u201cdance\u201d when they are not.<\/p>\n

\"\"<\/figure>\n

I quickly found a gap in my knowledge when trying to build this out. It\u2019s hard! But in the process, I discovered that easing functions play a big role in it.<\/p>\n

I turned to JavaScript to draw a bunch of concentric circles in SVG using a library:<\/p>\n

for (i = 1; i <= 10; i++) {\r\n  drawCircle({radius: i * 10});\r\n}<\/code><\/pre>\n

This was the result:<\/p>\n

\"\"<\/figure>\n

But that clearly does not look anything like the picture.<\/p>\n

As I thought things through, I realized that I was looking for a certain property. I wanted the change in radius of the concentric circles to be small at the beginning and then become larger as the radius increases.<\/p>\n

This means that the linear increase in radius using i++<\/code> won\u2019t do the trick. We need a better formula to derive the radius. So, my next attempt looked something like this:<\/p>\n

let i = 1;\r\nlet radiusList = [];\r\nlet radius = 0;\r\nwhile (i <= 10) {\r\n  drawCircle({radius: i * 10});\r\n  if(i < 4) { i = i + 0.5 } else { i = i + 1 } \r\n}<\/code><\/pre>\n

…which got me this:<\/p>\n

\"\"<\/figure>\n

Hmm, still not what I wanted. In fact, this deviates even further from the pattern. Plus, this code is hardly customizable unwieldy to maintain.<\/p>\n

So, I turned to math for one last attempt.<\/p>\n

What we need is a function that changes the radius organically and exponentially. I had an \u201cAha!\u201d moment and maybe you already see it, too. Easing functions will do this!<\/p>\n

The radius of each circle should increase slowly at first, then quickly as the circles go outward. With easing, we can make move things along a curve that can slow and speed up at certain points.<\/p>\n

A quick Google search landed me at this gist<\/a> which is a well-documents list of easing functions and really saved my day. Each function takes one input value, runs formulae. and provides an output value. The input value has to be between 0 and 1. (We will dig into this reasoning later.)<\/p>\n

A quadratic easing function looked promising because all it does is square the value it receives:<\/p>\n

function (t) { return t*t }<\/code><\/pre>\n

Here\u2019s the code I wound up using:<\/p>\n

const easing = (t) => {\r\n  return t*t\r\n}\r\nfor(i = 0; i<=1; i=i+0.05) {\r\n  const r = easing(i) * 40;\r\n  drawCircle(r);\r\n}<\/code><\/pre>\n

And we have a winner!<\/p>\n

\"\"<\/figure>\n

The difference between this pattern and my first two attempts was night and day. Yay for easing functions!<\/p>\n

This little experience got me really interested in what else easing functions could do. I scoured the internet for cool information. I found old articles, mostly related to Flash and ActionScript which had demos showing different line graphs.<\/p>\n

That\u2019s all pretty outdated, so here\u2019s my little primer on easing functions.<\/p>\n

What are easing functions?<\/h3>\n

They\u2019re a type of function that takes a numeric input between 0 and 1. That number runs through the specified function and returns another number between 0 and 1. A value between 0-1 multiplied by another value between 0-1 always results in a value between 0-1.<\/strong> This special property helps us make any computation we want while remaining within specific bounds.<\/p>\n

The purpose of an easing function is to get non-linear values<\/strong> from linear value inputs<\/strong>.<\/p>\n

This is the crux of what we need to know about easing functions. The explanations and demos here on out are all geared towards driving home this concept.<\/p>\n

Easing functions are a manifestation of the interpolation concept in mathematics<\/a>. Interpolation is the process of finding the set of points that lie on a curve. Easing functions are essentially drawing a curve from point 0 to point 1 by interpolating (computing) different sets of points along the way.<\/p>\n

Robert Penner was the first to define easing functions and create formulae for different ones in his book<\/a>.<\/p>\n

The five types of easing functions<\/h3>\n

There are five types of easing functions. They can be mixed, inverted and even mashed together to form additional, more complex functions. Let\u2019s dig into each one.<\/p>\n

Linear easing functions<\/h4>\n

This is the most basic form of easing. If the interval between the points we interpolate between 0 and 1 are constant, then we then form a linear easing function.<\/p>\n

Going back to the concentric circles example earlier, increasing the radius of the initial circle by a constant amount (10px in that example) makes a linear function.<\/p>\n

\"\"<\/figure>\n

It should come as no surprise that linear is the default easing function. They\u2019re extremely simple because there is no curve to the animation and the object moves in a straight, consistent direction. That said, linear functions have their drawbacks. For example, linear animations tend to feel unnatural or even robotic because real-life objects rarely move with such perfect, straight motion.<\/p>\n

Quadratic easing functions<\/h4>\n

A quadratic easing function is created by multiplying a value between 0 and 1 by itself (e.g. 0.5*0.5). As we learned earlier, we see that this results in a value that is also between 0 and 1 (e.g. 0.5*0.5 = 0.25).<\/p>\n

To demonstrate, let\u2019s make 10 values between 0 and 1 with a quadratic function.<\/p>\n

const quad_easing = (t) => t*t;\r\nlet easing_vals = [];\r\nfor(let i = 0; i < 1; i +=0.1) {\r\n  easing_vals.push(quad_easing(i));\r\n}<\/code><\/pre>\n

Here\u2019s a table of all the values we get:<\/p>\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
Input Value (x-axis)<\/th>\nQuadratic Eased Value (y-axis)<\/th>\n<\/tr>\n<\/thead>\n
0<\/td>\n0<\/td>\n<\/tr>\n
0.1<\/td>\n0.01<\/td>\n<\/tr>\n
0.2<\/td>\n0.04<\/td>\n<\/tr>\n
0.3<\/td>\n0.09<\/td>\n<\/tr>\n
0.4<\/td>\n0.16<\/td>\n<\/tr>\n
0.5<\/td>\n0.25<\/td>\n<\/tr>\n
0.6<\/td>\n0.36<\/td>\n<\/tr>\n
0.7<\/td>\n0.49<\/td>\n<\/tr>\n
0.8<\/td>\n0.64<\/td>\n<\/tr>\n
0.9<\/td>\n0.81<\/td>\n<\/tr>\n
1<\/td>\n1<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n

If we were to plot this value on a graph with x-axis as the original value and y-axis as the eased value, we would get something like this:<\/p>\n

\"\"<\/figure>\n

Notice something? The curve is practically the same as the ease-in functions we commonly find, even in CSS!<\/p>\n

Cubic, Quartic and Quintic easing functions<\/h4>\n

The final three types of easing functions behave the same, but work with a different value.<\/p>\n

A cubic easing function is creating by multiplying a value between 0 and 1 by itself three times. In other words, it\u2019s some value (e.g. t), cubed (e.g. t3<\/sup>).<\/p>\n

Quartic functions do the same, but to the power of 4. So, if t is our value, we\u2019re looking at t4<\/sup><\/p>\n

And, as you have already guessed, a quintic function runs to the power of 5.<\/p>\n

The following demo will give you a way to play around with the five types of functions for a good visual of how they differ from one another.<\/p>\n

See the Pen Plotting Easing functions<\/a> by Pavithra Kodmad (@pkodmad<\/a>) on CodePen<\/a>.<\/p>\n

Easing in and easing out\u2026or both!<\/h3>\n

\u201cAn ease-in-out is a delicious half-and-half combination, like a vanilla-chocolate swirl ice cream cone.\u201d
\n\u2014 Robert Penner<\/small><\/p><\/blockquote>\n

Ease in and ease out might be the most familiar easing animations. They often smooth out a typical linear line by slowing down at the start or end (or both!) of an animation.<\/p>\n

Ease-in and ease-out animations can be created using any of the non-linear functions we\u2019ve already looked at, though cubic functions are most commonly used. In fact, the CSS animation<\/code><\/a> property comes with ease-in<\/code> and ease-out<\/code> values right out of the box, via the animation-timing-function<\/code> sub-property.<\/p>\n