{"id":3947,"date":"2010-02-17T20:22:24","date_gmt":"2010-02-17T18:22:24","guid":{"rendered":"http:\/\/www.chipwreck.de\/blog\/?p=3947"},"modified":"2018-01-10T13:41:18","modified_gmt":"2018-01-10T12:41:18","slug":"mootools-transitions-explained","status":"publish","type":"post","link":"https:\/\/www.chipwreck.de\/blog\/2010\/02\/17\/mootools-transitions-explained\/","title":{"rendered":"Mootools Transitions explained"},"content":{"rendered":"<p>\t<script type=\"text\/javascript\" src=\"\/blog\/wp-content\/themes\/chipwreck\/js\/mootools-1.2.5-core-yc.js\"><\/script><br \/>\n\t<script type=\"text\/javascript\" src=\"\/blog\/wp-content\/themes\/chipwreck\/js\/mootools-1.2.4.4-more-all-yc.js\"><\/script><br \/>\n\t<script type=\"text\/javascript\" src=\"\/blog\/wp-content\/themes\/chipwreck\/js\/chipwreck.js\"><\/script><\/p>\n<h4 class=\"desc\">An in-depth tutorial about Mootools Transitions<\/h4>\n<p>Usually when using an effect I used to try out possible transitions one after another until I found the right one, but this got quite boring after some time, so I looked at the mootools source code to understand the logic behind &#8211; that&#8217;s what this tutorial is about.<!--more--><\/p>\n<p class=\"small\">\nGeneral information can be found here: <a href=\"http:\/\/mootools.net\/docs\/core\/Fx\/Fx.Transitions\" class=\"external\">mootools.net\/docs\/core\/Fx\/Fx.Transitions &raquo;<\/a> and also here: <a href=\"http:\/\/ryanflorence.com\/mootools-fx-transitions-demo\/\" class=\"external\"> ryanflorence.com\/mootools-fx-transitions-demo\/ &raquo;<\/a>\n<\/p>\n<h3>What is a transition?<\/h3>\n<blockquote><p>\nThe process or a period of changing from one state or condition to another.<\/p><\/blockquote>\n<p>This is the dictionary definition &mdash; in our case, when using transitions for Mootols Effects this means <q>the process of changing (element-)values from a beginning state to an ending state<\/q>.<\/p>\n<h4>The example<\/h4>\n<p>So as an example let&#8217;s use Fx.Tween to change the element width from 50px to 550px in 1 second. Here are several examples of transitions &#8211; trigger them by clicking the pink boxes.<\/p>\n<p class=\"small\"><strong class=\"pink\">If the demo doesn&#8217;t work: Reload the page, this should help (or write a comment if the problem persists).<\/strong><\/p>\n<style type=\"text\/css\">\n#transexample, #transexample2 {\n\tpadding: 5px 0px 5px 5px; \n\twidth: 550px;\n\tborder-right: 1px solid #9F9F9F;\n\tmargin-bottom: 2em;\n\tbackground-color: #d2d9db;\n}<\/p>\n<p>.trdesc {\n\tfont-size: 11px;\n\tline-height: 13px;\n\tvertical-align: bottom;\n\tcolor: #444;\n}<\/p>\n<p>.trexample {\n\theight: 16px;\n\twidth: 50px;\n\tmargin-bottom: 2px;\n\tbackground-color: #f257af;\n\tcursor: pointer;\n}\n<\/style>\n<p><script type=\"text\/javascript\">\nwindow.addEvent('domready', function() {<\/p>\n<p>\tvar trans = ['linear', 'sine:in', 'quad:in' ,'cubic:in', 'quart:in', 'quint:in', 'circ:in', 'pow:in', 'pow:out', 'elastic:out', 'bounce:in', 'bounce:out', 'bounce:in:out', 'back:in', 'back:out'];<\/p>\n<p>\tfor (j = 0; j < trans.length; j++) {\n\n\t\tmyhead = new Element('span', {'class' : 'trdesc', 'html': trans[j], 'id': 'desc'+j});\n\t\tmyelem = new Element('div', {'class' : 'trexample', 'id': 'ex'+j});\n\t\tmyelem.setStyle('background-color', [240,50+2*j,100+4*j].rgbToHex());\n\t\t\n\t\tmyelem.addEvent('click', function(event, el) {\n\t\t\tif (this.getStyle('width').toInt() > 50) {\n\t\t\t\tif (this.get('tween')) {\n\t\t\t\t\tthis.get('tween').cancel();\n\t\t\t\t}\n\t\t\t\tthis.setStyle('width', 50);\n\t\t\t}\n\t\t\telse {\t\t\t\n\t\t\t\tj = this.id.substring(2).toInt();\n\t\t\t\tthis.set('tween', {duration: 'long', transition: trans[j]});\n\t\t\t\tthis.tween('width', [50, 550]);\n\t\t\t}\n\t\t});<\/p>\n<p>\t\t$('transexample').adopt(myhead, myelem);\n\t};<\/p>\n<p>});<\/p>\n<p>\tfunction triggerAll()\n\t{\n\t\t$$('#transexample .trexample').each(function(el, i) {\n\t\t{\n\t\t\tel.fireEvent('click');\n\t\t}});\n\t};<\/p>\n<p>\tfunction resetAll()\n\t{\n\t\t$$('#transexample .trexample').each(function(el, i) {\n\t\t{\n\t\t\tel.setStyle('width', 50);\n\t\t}});\n\t}<\/p>\n<p><\/script><\/p>\n<p><a onclick=\"triggerAll()\">Trigger all &raquo;<\/a> | <a onclick=\"resetAll()\">Reset all &raquo;<\/a><\/p>\n<div id=\"transexample\"><\/div>\n<h3>How to use transitions<\/h3>\n<p>This should be nothing new, here the javascript I used for the examples above:<\/p>\n<pre lang=\"js\">\r\n$('element').addEvent('mousedown', function(event) {\r\n\tthis.set('tween', {duration: 'long', transition: 'cubic:in'});\r\n\tthis.tween('width', [50, 550]);\r\n});\r\n<\/pre>\n<p>Alternatively you can write the transition with its classname:<\/p>\n<pre lang=\"js\">\r\ntransition: Fx.Transitions.Cubic.EaseIn\r\n<\/pre>\n<p class=\"small\">Which notation you use is up to you &#8211; if you use the string representation, mootools automatically finds the appropriate Fx.Transitions-class.<\/p>\n<h3>Elements of a transition<\/h3>\n<p>Mootools transitions consist of three elements:<\/p>\n<ul>\n<li>Duration<\/li>\n<li>Type of transition<\/li>\n<li>An additional <q>ease<\/q>-value (if the type is not <q>linear<\/q>)<\/li>\n<\/ul>\n<p>In our example the transition takes the element width and transforms it from the starting value 50 to the target value 500 in one second. The type <q>decides<\/q> how the in-between values are being calculated, the <q>ease<\/q> decides from which <q>direction<\/q> the formula is applied &#8211; more about this later on.<\/p>\n<h4>Duration<\/h4>\n<p>This is simply the duration is it takes to change the values &#8211; in microseconds, so a duration of 1000 equals 1 second.<\/p>\n<p>There are three predefined durations:<\/p>\n<div class=\"math\">\n short: 250<em>ms<\/em> = &frac14; second<br \/>\n normal: 500<em>ms<\/em> = &frac12; second<br \/>\n long: 1000<em>ms<\/em> = 1 second\n<\/div>\n<h3>How are transitions calculated?<\/h3>\n<p>Let&#8217;s use the above example, the width of an element is being tweened from 50 to 550 pixel, with a duration of 1000 ms. So our starting value <em>from<\/em> is 50, the target value <em>to<\/em> is 550. That means we&#8217;ve got to cover a <q>distance<\/q> of 500 pixels in one second.<\/p>\n<p>Now let&#8217;s say our transition is expressed as a function <em>f(x)<\/em>, this is the code used in mootools:<\/p>\n<div class=\"math\">\n<em>delta<\/em> = <em>f<\/em>((<em>current_time<\/em> &minus; <em>starting_time<\/em>) \/ <em>duration<\/em>)<br \/>\n<em>new_value<\/em> = (<em>to<\/em> &minus; <em>from<\/em>) * <em>delta<\/em> + <em>from<\/em>;\n<\/div>\n<p class=\"small\">This is the mathematical notation, the mootools source code looks more javascript-like of course.<\/p>\n<p>(<em>current_time &#8211; starting_time<\/em>) = the number of milliseconds since the effect was started<\/p>\n<p>The argument of the function is <em>time difference divided by duration<\/em> &#8211; at the beginning this is about 0.0, after 500 ms this value is 0.5, at the end its approximately 1.0. So the transition function is applied to a range from 0.0 to 1.0 (<em>normalized<\/em>).<\/p>\n<p>Let&#8217;s assume we use a linear transition, so <em>f(x)<\/em> = <em>x<\/em>:<br \/>\nSo the new_value (our new width) is 0.0 to 1.0 times the range (500) plus the initial value (50). Or: At the beginning the width is set to 50 (initial value), after half the time we&#8217;ve got 500*0.5+50 = 300, and at the end 500*1.0+50 = 550.<\/p>\n<p>In this case the values from 50 to 500 are distributed uniformly along the unit interval from 0.0 to 1.0 &mdash; a linear function.<\/p>\n<h3>Types of Transitions<\/h3>\n<p>These are: Linear, Quad, Cubic, Quart, Quint, Pow, Expo, Circ, Sine, Back, Bounce and Elastic. Now I&#8217;ll explain how they work.<\/p>\n<h5>Linear Transition<\/h5>\n<p>A linear transition has no additional <q>ease<\/q>-parameter, since it simply divides the range equally along the timeline, as seen above.<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = <em>x<\/em>\n<\/div>\n<h5>Polynomial (<em>x<sup>n<\/sup><\/em>)  Transitions<\/h5>\n<p>In this category we&#8217;ve got: Quad, Cubic, Quart, Quint, Pow. All these are similar, only the exponent n of the function is changed &#8211; from 2 (=Quad) to 6 (=Pow). This is the following function:<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = <em>x<\/em><sup><em>n<\/em><\/sup>\n<\/div>\n<p>For these transitions the value will first increase slowly and near the end of the effect it will grow rapidly &#8211; like the well-known parabola.<\/p>\n<h5>Exponential Transition<\/h5>\n<p>The exponential transition puts x in the exponent (along with some factors):<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = 2<sup>8(<em>x<\/em>&minus;1)<\/sup>\n<\/div>\n<p>So the function grows even more rapidly towards the end &#8211; compared to the x<sup>n<\/sup>-transitions.<\/p>\n<h5>Circular Transition<\/h5>\n<p>The circular transition function describes a perfect circle (in this case a quadrant):<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = 1&minus; sin(arccos <em>x<\/em>)\n<\/div>\n<h5>Sinusoidal Transition<\/h5>\n<p>The sinusiodal transition delivers a graph which behaves like a part of a sine-curve, the result in this case is a smooth, nearly linear transition (see the graph below).<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = 1&minus; sin((1&minus;<em>x<\/em>) &sdot; <sup>\u220f<\/sup>\/<sub>2<\/sub>)\n<\/div>\n<h5>Back\/Bounce\/Elastic<\/h5>\n<p>These are special functions which use more complex formulas &#8211; have a look at the graph below to see how the back and elastic functions behave.<\/p>\n<h6>Back Transition<\/h6>\n<p>Back moves the value first in the opposite direction (in our case: the width gets smaller than 50 px) and then moves it in direction of the target value (view this in the example above).<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = <em>x<\/em><sup>2<\/sup> (2,618<em>x<\/em>&minus;1,618)\n<\/div>\n<h6>Elastic Transition<\/h6>\n<p>Elastic oscillates in increasing intervals between the opposite direction and the desired one. It&#8217;s best used with ease:out or ease:in:out, otherwise it may happen that effect doesn&#8217;t reach its target value.<\/p>\n<div class=\"math\">\n<em>f<\/em>(<em>x<\/em>) = 2<sup>10(<em>x<\/em>&minus;1)<\/sup>&sdot; cos(20&sdot;<em>x<\/em>&sdot;\u220f&sdot;<sup>1<\/sup>\/<sub>3<\/sub>)\n<\/div>\n<p>This transition appears like being on an elastic rope.<\/p>\n<h6>Bounce Transition<\/h6>\n<p>Bounce is the most complex function &#8211; it can&#8217;t be described as a simple formula. It first approaches the target value linear and then it oscillates between descreasing intervals, creating a <q>bouncing<\/q> effect.<\/p>\n<h3>Ease in and out<\/h3>\n<p><strong>Ease in<\/strong> is the default behaviour: Here the function is applied normally.<\/p>\n<p><strong>Ease out<\/strong> inverts the behaviour &#8211; so the effect works backwards.<\/p>\n<div class=\"math\">\n<em>g<\/em>(<em>x<\/em>) = 1&minus;<em>f<\/em>(1&minus;<em>x<\/em>)\n<\/div>\n<p><strong>Ease in and out<\/strong> is more complex: In the first half of the time the transition is applied normally, in the second half it is applied reverse.<\/p>\n<div class=\"math\">\nif (<em>x<\/em> &lt;= 0.5):<br \/>\n&nbsp;&nbsp;&nbsp;<em>g<\/em>(<em>x<\/em>) = <em>f<\/em>(2<em>x<\/em>) \/ 2<br \/>\notherwise:<br \/>\n&nbsp;&nbsp;&nbsp;<em>g<\/em>(x) = 2&minus; <em>f<\/em>(2(1&minus;<em>x<\/em>)) \/ 2\n<\/div>\n<h3>Transition functions visualized<\/h3>\n<p>This graph shows different transition functions (approximately):<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/www.chipwreck.de\/blog\/wp-content\/uploads\/2010\/02\/Transitions.png\" alt=\"\" title=\"Transitions\" width=\"470\" height=\"494\" class=\"alignnone size-full wp-image-3985\" srcset=\"https:\/\/www.chipwreck.de\/blog\/wp-content\/uploads\/2010\/02\/Transitions.png 470w, https:\/\/www.chipwreck.de\/blog\/wp-content\/uploads\/2010\/02\/Transitions-114x120.png 114w, https:\/\/www.chipwreck.de\/blog\/wp-content\/uploads\/2010\/02\/Transitions-285x300.png 285w\" sizes=\"auto, (max-width: 470px) 100vw, 470px\" \/><\/p>\n<h3>Values of transition functions<\/h3>\n<p>If you look at the graph above you might notice a pattern: the domain of transition functions is [0.0 &#x2025; 1.0] and the range is [&minus;0.5* &#x2025; 1.0]. The only exception is the <q>elastic<\/q> transition and here you should use it with ease:out, otherwise the desired output might not be what you want.<\/p>\n<p class=\"small\">* &minus;0.5 is not a definitive value, lower values are possible &mdash; but then some unpredicted results might happen.<\/p>\n<p>So generally speaking (and as nagaozen stated below) a transition function should start at (0,0) and end at (1,1).<\/p>\n<div class=\"math\">\n<em>f<\/em>: [0&#x2025;1] &rarr; [&minus;0.5&#x2025;1]<br \/>\nwith<br \/>\n<em>f<\/em>(0) = 0 and <em>f<\/em>(1) = 1\n<\/div>\n<h3>Creating an own transition function<\/h3>\n<p>In case this is not sufficient, mootools offers us the possibility to apply any function as a transition. Here&#8217;s an example:<\/p>\n<pre lang=\"js\">\r\nfunction powsin(p) {\r\n\treturn (Math.pow(p + 0.4, 3) * Math.sin(p - 0.5)); \/\/ our own function\r\n};\r\nvar transitionPowsin = new Fx.Transition(powsin);\r\n\r\nelement.set('tween', {duration: 'long', transition: transitionPowsin});\r\n<\/pre>\n<p class=\"small\">Don&#8217;t be confused by the variable &#8220;p&#8221;, it&#8217;s mootools standard in this case &#8211; you can also use &#8220;x&#8221; or whatever you like..<\/p>\n<p>Now the <q>powsin<\/q>-function isn&#8217;t the most useful transition ever, but take it as an example for own experiments.<\/p>\n<p>Here&#8217;s how it looks (click the pink rectangle to start):<\/p>\n<p><script type=\"text\/javascript\">\nwindow.addEvent('domready', function() {<\/p>\n<p>\tfunction powsin(p) {\n\t\treturn (Math.pow(p + 0.4, 3) * Math.sin(p - 0.5));\n\t};<\/p>\n<p>\tvar transitionPowsin = new Fx.Transition(powsin);<\/p>\n<p>\t$('minetr').addEvent('click', function(event, el) {\n\t\tif (this.getStyle('width').toInt() > 50) {\n\t\t\tif (this.get('tween')) {\n\t\t\t\tthis.get('tween').cancel();\n\t\t\t}\n\t\t\tthis.setStyle('width', 50);\n\t\t}\n\t\telse {\t\t\t\n\t\t\tj = this.id.substring(2).toInt();\n\t\t\tthis.set('tween', {duration: 'long', transition: transitionPowsin});\n\t\t\tthis.tween('width', [50, 550]);\n\t\t}\n\t});<\/p>\n<p>});\n<\/script><\/p>\n<div id=\"transexample2\">\n\t<span class=\"trdesc\">transitionPowsin:easeIn<\/span><\/p>\n<div class=\"trexample\" id=\"minetr\"><\/div>\n<\/div>\n<p>That&#8217;s it &#8211; Comments and Feedback of course welcome.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An in-depth tutorial about Mootools Transitions. How to use, how they work behind the scenes and how to create own transitions.<\/p>\n","protected":false},"author":2,"featured_media":3985,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[14],"tags":[55,10,54],"class_list":["post-3947","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-javascript","tag-javascript-mootools","tag-mootools","tag-track"],"jetpack_featured_media_url":"https:\/\/www.chipwreck.de\/blog\/wp-content\/uploads\/2010\/02\/Transitions.png","jetpack_shortlink":"https:\/\/wp.me\/paPEN-11F","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts\/3947","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/comments?post=3947"}],"version-history":[{"count":4,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts\/3947\/revisions"}],"predecessor-version":[{"id":8155,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/posts\/3947\/revisions\/8155"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/media\/3985"}],"wp:attachment":[{"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/media?parent=3947"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/categories?post=3947"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.chipwreck.de\/blog\/wp-json\/wp\/v2\/tags?post=3947"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}