{"id":33176,"date":"2014-01-13T17:30:18","date_gmt":"2014-01-13T17:30:18","guid":{"rendered":"http:\/\/rafaelfajardo.com\/portfolio\/1ucasvb-easing-functions-are-an-immensely\/"},"modified":"2018-12-06T13:02:51","modified_gmt":"2018-12-06T20:02:51","slug":"1ucasvb-easing-functions-are-an-immensely","status":"publish","type":"post","link":"https:\/\/rafaelfajardo.com\/portfolio\/1ucasvb-easing-functions-are-an-immensely\/","title":{"rendered":""},"content":{"rendered":"<div id='gallery-1' class='gallery galleryid-33176 gallery-columns-3 gallery-size-thumbnail'><figure class='gallery-item'>\n\t\t\t<div class='gallery-icon portrait'>\n\t\t\t\t<a href='https:\/\/rafaelfajardo.com\/portfolio\/1ucasvb-easing-functions-are-an-immensely\/attachment\/33177\/'><img loading=\"lazy\" decoding=\"async\" width=\"100\" height=\"100\" src=\"https:\/\/rafaelfajardo.com\/portfolio\/wp-content\/uploads\/tumblr_mj7bx09MDo1s5nl47o2_r1_500-100x100.gif\" class=\"attachment-thumbnail size-thumbnail\" alt=\"\" \/><\/a>\n\t\t\t<\/div><\/figure>\n\t\t<\/div>\n\n<p><a class=\"tumblr_blog\" href=\"http:\/\/1ucasvb.tumblr.com\/post\/44666043888\/easing-functions-are-an-immensely-useful-tool-for\">1ucasvb<\/a>:<\/p>\n<blockquote>\n<p><strong>Easing functions<\/strong> are an immensely useful tool for animators. They are very handy when we want to spice up an animation and give it an extra cool or polished look, and are incredibly simple to implement in code.<\/p>\n<p>The main idea is that you have a <strong>starting point A<\/strong> and an <strong>ending point B<\/strong>, and you want something to move from <strong>A<\/strong> to <strong>B<\/strong> along a (not necessarily straight) path connecting both points.<\/p>\n<p>However, the path between the points is not the only thing to consider: there\u2019s also how the object will traverse this path, how fast it\u2019ll move at each point, how it will accelerate, etc.<\/p>\n<p>What we are looking for is a uniform \u201cspeed\u201d parameterization of the path, that is, we want a function <strong>f<\/strong>(<em>t<\/em>) that returns a point in space along the path. The function is built so <strong>f<\/strong>(<em>t<\/em>=0) gives us the starting point and <strong>f<\/strong>(<em>t<\/em>=1) gives us the ending point. Additionally, for equally spaced values of <em>t<\/em> in the unit interval [0,1], we want equally spaced points along the path.<\/p>\n<p><a href=\"http:\/\/en.wikipedia.org\/wiki\/Differential_geometry_of_curves#Length_and_natural_parametrization\">Unit speed parameterization of curves<\/a> is not a trivial thing, but for a straight line path using linear interpolation \u2014 which is by far the most common \u2014 it is very straightforward: we don\u2019t have to do anything. It is already uniform in speed!<\/p>\n<p>This is where easing functions come in. The easing function e(<em>t<\/em>) takes an input value <em>t<\/em>, from 0 to 1, and returns a new value, not necessarily from 0 to 1 (to account for overshoots). The only constraint is is that e(0) = 0 and e(1) = 1. The value returned by the easing function is what we use to get the current position along the path.<\/p>\n<p>In math terms, if our path is given by <strong>f<\/strong>(<em>t<\/em>) and our easing function is e(<em>t<\/em>), we\u2019ll use <strong>f<\/strong>(e(<em>t<\/em>)) in our animation code.<\/p>\n<p>In the animation above, you see the result of using several different easing functions on a simple linear path.<\/p>\n<p>The horizontal value of each graph is the <em>t<\/em> time parameter, and the vertical value is the value returned by e(<em>t<\/em>). The box delimits the interval from [0,1] in both directions.<\/p>\n<p>Shown at right of each graph is the movement you get with this easing function. You can see that even the slightest variation from the super-lame straight line (top left) is already much nicer to look at.<\/p>\n<p>The functions shown here were all custom made, and are part of my personal animation library. Linear, power and sine are found everywhere, and are the most basic ones.<\/p>\n<p>Most libraries also include \u201celastic\u201d and \u201cbounce\u201d, among others, but these are always fixed B\u00e9zier curve or polynomial approximations, which are pretty bad since you can\u2019t fine-tune them to your needs. So I wrote my own.<\/p>\n<p>The trade off for being totally tunable is that they are not optimized for real time, but that isn\u2019t an issue for me.<\/p>\n<p>You\u2019ll also notice that I haven\u2019t included ease-in and ease-out separately. I find it mostly useless. I\u2019ve never seen anyone using \u201celastic\/bounce ease in\u201d, for instance, and I hope it has never been used by anyone. It looks like garbage, as you can see when the animations run backwards.<\/p>\n<p>In any case, creating mixed functions from these is very easy, just a matter of acting in reverse on half the interval, and subtracting the function from 1 for the ease-in parts.<\/p>\n<p><strong>POWER<\/strong><\/p>\n<p>This is usually found in three flavors out there: quad(tratic), cubic and quart(ic). I decided to just wrap them all in the same thing, as it\u2019s the same construction, except using different powers<\/p>\n<p>The idea is to use a variation of <em>t<\/em><sup><em>p<\/em><\/sup> and its reflection to create the ease-in and ease-out bits.<\/p>\n<p>In particular, you have (2<em>t<\/em>)<sup>p<\/sup>\/2 for <em>t<\/em> in [0,0.5] and 1 &#8211; (2(1-x))<sup>p<\/sup>\/2 (non-expanded for clarity) for <em>t<\/em> in (0.5,1]. All values p &gt; 0 are well-behaved in the unit interval.<\/p>\n<p><strong>SINE<\/strong><\/p>\n<p>This one is just simply sin(<em>t<\/em>\u00b7\u03c0\/2)<sup>2<\/sup>. You can easily get rid of that power using the familiar identity, but it looks cleaner this way.<\/p>\n<p><strong>BOUNCE<\/strong><\/p>\n<p>The bounce one is based on the actual physics of parabolic motion. It is tuned by two parameters: decay power and number of times it hits the ground. This means you can set, precisely, how many times you want it to bounce around, and you can fine tune how sharply it will lose energy after each bounce.<\/p>\n<p>I usually avoid using exponential decay on its own because it doesn\u2019t reach zero exactly at the end of the interval, which is usually more desirable than physically accurate decay rates. So I tend to use a factor of (1-<em>t<\/em>)<sup><em>p<\/em><\/sup> for decays in general. It offers more freedom anyway.<\/p>\n<p><strong>PHYSICAL<\/strong><\/p>\n<p>Most libraries include \u201celastic\u201d and \u201cback\u201d (which overshoots a bit). They look all right, but are not accurate models of physical motion, and you can\u2019t fine tune them much.<\/p>\n<p>My \u201cphysical\u201d easing function replaces both with a solution for dampened harmonic oscillation, where you can manually set the decay rate and frequency of oscillation. This means you can have exactly as many back-and-forth motions as you want. The exponential decay rate was also replaced by the more malleable (1-<em>t<\/em>)<sup><em>p<\/em><\/sup> expression.<\/p>\n<p>Using frequencies like 1 or 0.5 gives you a replacement for the \u201cback\u201d easing in other libraries, with the benefit of tuning. Frequencies that are not multiples of &frac12; tend to look bad, but thanks to the decay function they still end up at 1 no matter what.<\/p>\n<p><strong>UNIFORM<\/strong><\/p>\n<p>This is one of the most useful ones, and something like it is lacking everywhere I looked. In a lot of situations, it is desirable to have a \u201cmostly linear\u201d movement, with a steady speed in the middle of it. The biggest problem with linear interpolation is the ending points. Having the object static and suddenly starting to move looks jarring and unrealistic.<\/p>\n<p>The \u201cuniform\u201d easing I came up with is a way of keeping the best of both worlds: you can tune how much of the path will be linear, and how much of the remaining will be used by acceleration\/deceleration. You can also tune how aggressive acceleration\/deceleration will be.<\/p>\n<p>Due to its almost-linear nature, it works exceptionally well with other easing functions. This is shown in the last one (bottom right), where I used it along with the bounce function to give it an extra anticipation in both ends. It makes the bounce feel heavier. Looks pretty good!<\/p>\n<h3>Can you release these functions somewhere?<\/h3>\n<p>I will write a detailed post about each of them along with pseudocode if there\u2019s enough interest. Since these functions aren\u2019t meant to be used in real time applications, they are not ready to be used in a lot of contexts out there with a lot of moving objects. It would be pretty easy to cache these and make it super fast during run time, though.<\/p>\n<p>However, most people seem to be happy enough with their easing libraries, so I\u2019m not sure if it\u2019s worth the trouble, nor if tumblr is the best way to go about it.<\/p>\n<p>So if you are interested, please <a href=\"http:\/\/1ucasvb.tumblr.com\/ask\">drop me a request<\/a> so I know I won\u2019t be wasting time posting them here.<\/p>\n<\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>1ucasvb: Easing functions are an immensely useful tool for animators. They are very handy when we want to spice up an animation and give it an extra cool or polished look, and are incredibly simple to implement in code. The main idea is that you have a starting point A and an ending point B, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"gallery","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[],"tags":[1539],"class_list":["post-33176","post","type-post","status-publish","format-gallery","hentry","tag-emergent-digital-practices","post_format-post-format-gallery"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p6PWot-8D6","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/posts\/33176","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/comments?post=33176"}],"version-history":[{"count":1,"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/posts\/33176\/revisions"}],"predecessor-version":[{"id":33178,"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/posts\/33176\/revisions\/33178"}],"wp:attachment":[{"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/media?parent=33176"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/categories?post=33176"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rafaelfajardo.com\/portfolio\/wp-json\/wp\/v2\/tags?post=33176"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}