UIZE JavaScript Framework

GUIDES Javascript Animation And Effects

1. Introduction

The UIZE JavaScript Framework provides powerful features to support slick animation effects, with easing, bounce, elasticity, pulsing, and much more.

WHAT IS JAVASCRIPT ANIMATION?

JavaScript animation is the animation of properties of the DOM, CSS style properties, or the properties of JavaScript objects, using JavaScript code to drive this animation.

WHAT ALL CAN BE ANIMATED?

Many visible properties of a document can be animated, such as color style properties (eg. color, background, backgroundColor, borderColor, etc.), position style properties (eg. top, right, bottom, left, backgroundPosition), padding and margin style properties (eg. padding, paddingTop, paddingRight, paddingBottom, paddingLeft, margin, marginTop, etc.), dimension style properties (eg. width, height, maxWidth, maxHeigh, borderWidth, borderTopWidth, etc.), and font style properties (eg. fontSize, letterSpacing, wordSpacing, lineHeight, textIndent).

In addition, the UIZE JavaScript Framework lets you animate the values of state properties for instances of Uize.Class subclasses, calls to methods, and calls to arbitrary functions. So, beyond just visible style properties of a document, you can animate state of anything. And you're not even limited to time-based effects - you can even use the effects system to produce color gradients and other non-time based fades.

HOW'S THE PERFORMANCE?

The animation system of the UIZE JavaScript Framework is optimized for performance, using many tricks and techniques. Performance is surprisingly good (as you'll see from some of the examples), and browsers are improving all the time and machines are getting more powerful. Basically, things are generally looking up for animation and effects built using Web standards.

ANIMATION IS A KIND OF FADE

Some people may think of an opacity fade when they hear the term "fade" used, but in the UIZE JavaScript Framework the term "fade" refers to any kind of cross-fade between one state and another. This would include color fades, position fades, size fades, opacity fades, etc. Animations are really just a specific type of fade - a time-based fade - and not all fades need to occur over time (more on that later). Some people also use terms such as "interpolation", or "tweening". UIZE uses the term "fade", so prepare to encounter it with this meaning all throughout the documentation.

2. Some Examples

In case you do not already have a sense of what's possible with animation in the UIZE JavaScript Framework, and with JavaScript animation in general, you may want to first take a look at some examples.

If you are already familiar with what's possible and just want to start learning how to use JavaScript animation in your own Web projects, then you can ignore the examples listed below and skip straight to the next section.

2.1. Menu Link Effects

Fading Links - Demonstrates how the Uize.Widget.HoverFader widget class can be used to add an animated color fading effect to the links in five different menus.
Hover Fader for Thumbnails - Demonstrates how the Uize.Widget.HoverFader widget class can be used to add an animated effect to the thumbnails in several different sets of thumbnails.
Hover Fader Stretching Menu - Demonstrates how the Uize.Widget.HoverFader widget class can be used to create a stretching menu effect.
Hover Fader Color Effects - Who needs boring menus when you can have stunning menu animations that will have your users mesmerized! You have to see these effects to believe them.

2.2. Slideshow Type Transition Effects

ImageWipe - Demonstrates how the Uize.Widget.ImageWipe class can be used to wire up a div in a document in order to provide an elaborate and highly configurable JavaScript animation wipe effect to transition from one image to another.
Deck Swapper - Demonstrates how the Uize.Widget.Swap.Deck widget class can be used to wire up a deck of divs in a document in order to provide a transition effect when swapping from one item in the deck to another.
Basic HTML Swap - Demonstrates how the Uize.Widget.Swap.Html widget class can be used to wire up a div in a document in order to provide a JavaScript animation transition effect when swapping out its HTML.
Image Cycle - Demonstrates how the Uize.Widget.Swap.Image.Cycle widget class can be used to provide a simple cycling slideshow of images.
Uize.Widget.Swap.Image - Demonstrates how the Uize.Widget.Swap.Image widget class can be used to wire up a div in a document in order to provide a highly configurable yet lightweight (in terms of code, DOM, and performance) JavaScript animation effect when transitioning from one image to another.
Slideshow of Data - Demonstrates how the Uize.Widget.Swap.Image widget class can be used as part of the representation of slides in a slideshow user interface in order to achieve a dissolve / crossfade transition effect when navigating from one slide to another.
Slideshow With Dissolve - Demonstrates how the Uize.Widget.Swap.Image widget class can be used to represent slides in a slideshow in order to achieve a dissolve / crossfade transition effect when navigating from one slide to another.

2.3. Widgets With Animation

Scrolly Carousel - Demonstrates how you can use the Uize.Widget.Scrolly widget class to create a carousel scrolly that lets you step through a series of pages, with an accompanying JavaScript animation effect.
Scrolly - Demonstrates the use of two instances of the Uize.Widget.Scrolly widget class - one for a horizontal scrolly, and the other for a vertical scrolly.
Coupled Zooming Collection Items - Demonstrates how the Uize.Util.Coupler class can be used to easily couple together two instances of the Uize.Widget.CollectionItem.Zooming widget class.
Zooming Collection Items - Demonstrates how the Uize.Widget.CollectionItem.Zooming widget class can be used to add a JavaScript animation zoom in effect to a set of thumbnails.
Mag View - Demonstrates how the Uize.Widget.MagView class can be used to provide a lightweight detail view interaction to an image.
Tabbed Interface With Fade - Demonstrates how the Uize.Widget.Options.Tabbed widget class can be used to wire up the markup for a tabbed interface, where switching from one tab to another is accompanied by a JavaScript animation transition effect.
Basic Progress Bar - Demonstrates how you can use the Uize.Widget.Bar.Progress widget class to provide feedback on the progress of a task of indeterminate length (such as an AJAX request).

2.4. Reveal Effects

Sequenced Show Using Swap - Demonstrates use of the Uize.Array.Order.jumble method of the Uize.Array.Order package in conjunction with the Uize.Node.find method in order to sequence the showing of thumbnail images in a grid, with a JavaScript animation reveal effect provided by the Uize.Widget.Swap class.
Uize.Widget.ThumbZoom - Demonstrates how the Uize.Widget.ThumbZoom widget class can be used to wire up an aribitrary number of thumbnail images on the page, so that clicking on a thumbnail loads its larger version and then displays it using a zoom out JavaScript animation effect.

2.5. Miscellaneous Examples

Fading an Object - Demonstrates the use of arbitrarily complex data structures for the startValue and endValue state properties of a Uize.Fade instance.
Basic Mask - Demonstrates how the Uize.Widget.Mask widget class can be used to highlight a region of a layout, with an accompanying animation of the mask's coordinates when a new region is to become highlighted.

3. The Engine

The engine for animation and fade effects in the UIZE JavaScript Framework is the Uize.Fade class.

All classes or modules that implement some form of animation ultimately rely on the Uize.Fade class. So, even when you're not using the Uize.Fade class directly, it's worth understanding the principles of this class, since it's used to drive so many diverse animations throughout various parts of the framework. Learning the basic mechanics of this class will take you a long way towards understanding all animation effects.

3.1. In a Nutshell

In simple terms, the Uize.Fade class interpolates a value between a start value and an end value.

When this interpolation is driven by its timer, an instance of this class can be used to control an animation over time. Code that uses a Uize.Fade instance can wire handlers for various events in order to be notified when value updates - and other key state changes - occur. Let's consider a simple example...

EXAMPLE

var myFade = Uize.Fade ({startValue:0,endValue:100,duration:5000});
myFade.wire ('Changed.value',function () {Uize.Node.setValue ('testNode',myFade)});
myFade.start ();

In the above example, a value will be faded between 0 and 100 over a period of 5000 milliseconds (5 seconds) when the start instance method is called. In order to have something noticeable happen during the fade, a handler is wired to the Changed.value instance event - an event that is fired each time the value state property is updated (if you need a refresher on the Change.[propertyName] Virtual Event, consult the State Properties guide and read through the Changed Events section).

In this case, the handler code simply displays the current value in the DOM node with the id of 'testNode', using the Uize.Node.setValue static method of the Uize.Node module. We can pass just the reference to myFade here because the Uize.Node.setValue method will coerce it to a string and thereby invoke the valueOf Intrinsic Method which returns the value of the value state property - a nice little shorthand. Now, if we didn't wire a handler to this event, then the value would still fade when the start method was called, but nobody would see that anything was happening.

3.2. Key Features

The Uize.Fade class supports the following key features...

Quantization - In order to provide safe values for code that uses fades, and in order to improve performance, interpolated values can be quantized using the highly flexible quantization feature.
Compound Value Interpolation - Start and end values for a fade don't need to be exclusively simple number type values - they can be arrays of numbers, or arrays of arrays of numbers, or objects containing numbers, etc.
Curves - Linear is boring. The Uize.Fade class lets you supply arbitrary curve functions in order to produce animations that emulate the complex properties of motion, letting you achieve effects like bounce, springiness, wobble, elasticity, etc.
Non-time Based Fades - Fades do not need to occur exclusively in the time domain. You can use the Uize.Fade class to produce color gradients, to lay out an array of DOM nodes, etc.

3.3. Quantization

In order to provide safe values for code that uses fades, and in order to improve performance, interpolated values can be quantized using the highly flexible quantization feature.

The Uize.Fade class provides a highly versatile mechanism for configuring aribtrary quantization. In our earlier example that displayed an interpolated number in the range of 0 to 100 in a DOM node during the fade, there was no quantization. Consequently, you would see all manner of floating point number displayed throughout the course of the fade. If we were instead using this interpolated value to set something like left position, measured in pixels, then we wouldn't have a healthy value. And even if we rounded the number in our Changed.value event handler code, or if the browser forgave floating point pixel measurements, we would still potentially be touching the DOM far more than we would need to - the fractional values will not be noticeable but the unnecessary updates will cost us in performance. This is where the quantization state property of the Uize.Fade class comes in. Consider an updated version of the earlier example...

EXAMPLE

var myFade = Uize.Fade ({startValue:0,endValue:100,duration:5000,quantization:1});
myFade.wire ('Changed.value',function () {Uize.Node.setValue ('testNode',myFade)});
myFade.start ();

By setting the value of the quantization state property to 1, we are ensuring that the value of the value state property will always be in increments of 1. Since the start value is an integer, this will ensure that the interpolated value at any given point in time will always be an integer. Now when the start method is called, you would only see integers displayed throughout the course of the fade.

3.4. Compound Value Interpolation

Possibly one of the most powerful features of the Uize.Fade class is its support for interpolation of compound values.

Start and end values for a fade don't need to be exclusively simple number type values - they can be arrays of numbers, or arrays of arrays of numbers, or objects containing properties with number values, etc. Consider the very practical use case of animating the coordinates of an absolutely positioned DOM node over time by fading the values of its left, top, width, and height CSS style properties...

EXAMPLE

var positionFade = Uize.Fade ({
  startValue:{left:0,top:0,width:10,height:10},
  endValue:{left:100,top:100,width:200,height:200},
  duration:2000,
  quantization:1
});
positionFade.wire (
  'Changed.value',
  function () {Uize.Node.setStyle ('myNode',positionFade.get ('value'))}
);
positionFade.start ();

In the above example, the DOM node with the id of 'myNode' is being moved and resized, starting from a position of 0,0 and a size of 10 x 10, and ending up at the position of 100,100 and a size of 200 x 200. Because the values of the startValue and endValue state properties are both objects containing the properties left, top, width, and height, so the value of the value state property is also an object containing these properties. The Uize.Node.setStyle static method conveniently accepts an object with an arbitrary number of properties for different CSS style properties, and left, top, width, and height happen to be valid names of CSS style properties. Furthermore, this method resolves numerical values for coordinate properties by appending the unit string 'px'. So we're golden - we can just pass the value of the fade's value state property to the Uize.Node.setStyle method and it will position and resize the DOM node as desired.

Now this, of course, is not the most concise way to animate coordinates using the UIZE JavaScript Framework - the framework provides convenient modules for easily animating CSS style properties - but this example illustrates the benefit of interpolating compound values. And those other, more convenient features for easily animating CSS properties rely on this mechanism, anyway.

Now let's consider a slightly more complex example - one where we want to animate both the coordinates and background color of a DOM node using the same Uize.Fade instance...

EXAMPLE

var positionAndBgFade = Uize.Fade ({
  startValue:{
    coords:{left:0,top:0,width:10,height:10},
    bg:{red:255,green:165,blue:0}
  },
  endValue:{
    coords:{left:0,top:0,width:10,height:10},
    bg:{red:128,green:0,blue:128}
  },
  duration:2000,
  quantization:1
});
positionAndBgFade.wire (
  'Changed.value',
  function () {
    var
      value = positionAndBgFade.get ('value'),
      bg = value.bg
    ;
    Uize.Node.setStyle ('myNode',value.coords);
    Uize.Node.setStyle (
      'myNode',
      {backgroundColor:'rgb(' + bg.red + ',' + bg.green + ',' + bg.blue + ')'}
    );
  }
);
positionAndBgFade.start ();

Now the values for the startValue and endValue state properties have even more in them - this time separate coords and bg properties, where both coords and bg are objects. No problem, the Uize.Fade class can handle it all. The value of the value state property, that is interpolated between startValue and endValue, will have the same structure as startValue and endValue. In the handler for the Change.value event, the code is indexing into this interpolated compound value to get the interpolated values for coords and bg, which it is then using separately to set the coordinates and background color for the node. With the interpolated background color tuple object it is forming a string of the form "rgb([red],[green],[blue])" for setting the backgroundColor CSS style property.

Now, once again, there are more convient ways to do this in a single statement using the Uize.Fx module, but this example illustrates the versatility of compound value interpolation.

3.4.1. Compound Values and Compound Quantization

Along with compound value interpolation, the Uize.Fade class also supports compound quantization.

In the previous example that showed how quantization is used, the quantization value of 1 was being used for the interpolation of all components of the compound value. But, what if different parts of a compound value need different quantization? Say, for example, we wanted to use a single Uize.Fade instance to animate both the opacity and color of a DOM node. If we used the value 1 for quantizing the opacity value (a floating point number in the range of 0 to 1), then it could only ever be the integers 0 or 1. In such cases, it is possible to specify a compound value for the quantization state property. Consider the following example...

EXAMPLE

var positionAndBgFade = Uize.Fade ({
  startValue:{opacity:1,bg:{red:255,green:165,blue:0}},
  endValue:{opacity:0,bg:{red:128,green:0,blue:128}},
  duration:2000,
  quantization:{bg:1}
});
positionAndBgFade.wire (
  'Changed.value',
  function () {
    var
      value = positionAndBgFade.get ('value'),
      bg = value.bg
    ;
    Uize.Node.setStyle (
      'myNode',
      {
        opacity:value.opacity,
        backgroundColor:'rgb(' + bg.red + ',' + bg.green + ',' + bg.blue + ')'
      }
    );
  }
);
positionAndBgFade.start ();

Now we have a quantization value of 1 for the bg part of the interpolated value, but no quantization specified for the opacity part (so it defaults to no quantization). Of course, life is made more convenient by the Uize.Fx.fadeStyle method of the Uize.Fx module, where it is not necessary to worry about which CSS style properties need which quantization and where the above task could be accomplished in a single statement, but this example is to illustrate the principle.

4. The Fade Factory

The UIZE JavaScript Framework provides a higher level construct for initiating fades without having to deal directly with the Uize.Fade class.

In the section The Engine we looked at the most atomic unit of animations: an instance of the Uize.Fade class. When using the Uize.Fade class directly, it is your responsibility to keep track of the fade instances you create, wire event handlers for them, start them and and stop them as desired, etc. For certain situations where you just want to quickly kick off an animation and where your code doesn't have a long-term interest in holding on to the Uize.Fade instance used to service the animation, the Uize.Fade.xFactory extension module comes in, providing a number of useful factory methods for initiating fades in a carefree manner.

EXAMPLE

Uize.Fade.fade (
  function (value) {Uize.Node.setStyle ('myNode',value)},  // update handler function
  {left:0,top:0,width:10,height:10},                       // start value
  {left:100,top:100,width:200,height:200},                 // end value
  2000,                                                    // duration
  {quantization:1}                                         // extra fade properties
);

The above example is a reformulation of the first example shown in the compound Value Interpolation section, to now use the Uize.Fade.fade static method that is defined in the Uize.Fade.xFactory extension module. If you compare the two examples, you will notice that this one is shorter. It's still not as short as it could be, because we're not using the convenient Uize.Fx.fadeStyle static method that's defined in the Uize.Fx module and that's designed specifically for the purpose of making animating CSS style properties dead simple. It is, however, shorter than the example that directly uses the Uize.Fade class, because it leaves it to the Uize.Fade.fade method to create the Uize.Fade instance, wire event handlers, and start the fade.

Looking at the example, you should notice a few important things:

1.  The first parameter is the update handler function, and it receives the interpolated value as its parameter.
2.  The second and third parameters are the start and end values for the fade, respectively (ie. the values for the Uize.Fade instance's startValue and endValues state properties).
3.  The fourth parameter is the fade's duration (ie. the value for the Uize.Fade instance's duration state property).
4.  The last parameter is for additional state property values that should be set on the Uize.Fade instance before the fade is started (in this case we're using it to set quantization).

4.1. Non-interpolated Values

The interpolation of compound values by the Uize.Fade class ignores parts of the compound value that are the same between the start and end values.

So, for example, if the start value was the array ['myNode',1] and the end value was the array ['myNode',0], then the first element of the interpolated array would not be interpolated, because the value of this element in the compound start value is the same as its value in the compound end value. This is just as well, too, because interpolating between two string values would be a bit of a challenge. So, for all values interpolated between the compound start and end values, the value of the first element of the array would always be 'myNode'.

This particular behavior comes in handy when we want to interpolate an arguments array for a function call, between a start arguments array and an end arguments array. Consider the following example...

EXAMPLE

Uize.Fade.fade (Uize.Node.setOpacity,['myNode',1],['myNode',0],2000);

In the above example, we are animating calls to the Uize.Node.setOpacity static method defined in the Uize.Node module in order to fade the opacity of the node with the id of 'myNode' from 1 to 0 over a period of 2000 milliseconds (2 seconds). The start and end values for the fade are arguments arrays for the function call, with the first argument specifying the DOM node and the second argument specifying the opacity level. What is interpolated for each update of the fade is an arguments array where the first element will always be 'myNode', and the second element will be an interpolated floating point number in the range of 1 to 0.

This principle applies fundamentally to the way that the Uize.Fade class does interpolation, so we get the benefit of it in the Uize.Fade.fade static method - and all the other factory static methods that are implemented by the Uize.Fade.xFactory module - because the Uize.Fade.xFactory module is built on top of the Uize.Fade class.

4.2. Fading a Function Call

In the most basic case, you may wish to animate the calling of an update function.

In such cases, the generic Uize.Fade.fade static method will do the job. For this method, the start value can be an array that represents the values for the arguments of the function call at the start of the fade. Similarly, the end value can be an array for the arguments at the end of the fade. At every update, the Uize.Fade class will interpolate an arguments set, whose values are somewhere between the arguments' values at the start and end of the fade, and then supply that interpolated arguments set to the function when calling it. Consider the following example...

EXAMPLE

Uize.Fade.fade (scrollTo,[0,0],[0,200],500);

In the above example, the vertical scroll position of the document will be faded from 0 to 200 over a half second.

The scrollTo function is a property of the window object - it really doesn't have to be called as a method on the window object. It takes two parameters: left scroll position, and top scroll position. Using the Uize.Fade.fade method to fade calls to this function, a start parameter list of [0,0] is specified, and an end parameter list of [0,200] is specified. This has the effect of fading the scroll position of the window from 0,0 to 0,200. In this example, the left scroll position is the same at the start and end of the fade, but there's no saying that it has to be.

Being able to easily fade function calls with interpolated argument lists is very powerful and makes it easy to do quite a lot in just a short statement. In another example, one could achieve a window roll down effect with a statement like Uize.Fade.fade (resizeTo,[1024,0],[1024,768],1000).

4.2.1. Fading Anonymous Function Calls

There's no saying that a function that is being faded using the Uize.Fade.fade method has to be a named function - it could just as well be anonymous.

For an example of this, refer back to the first example of the section The Fade Factory.

4.2.2. Fading Static Methods As Functions

For fading static methods, one can usually just use the Uize.Fade.fade method.

This is because most static methods don't care about the context on which they are called and are really just static properties that happen to be references to functions. This is the case with most of the static methods defined in package modules, such as the Uize.Node.setOpacity static method of the Uize.Node module. So, the following two statements would be equivalent...

Uize.Fade.fade (Uize.Node.setOpacity,['myNode',1],['myNode',0],2000);

Uize.Fade.fadeMethod (Uize.Node,'setOpacity',['myNode',1],['myNode',0],2000);

In the above example, both statements would have the effect of fading the opacity of the node with the id of 'myNode' from 1 to 0 over a period of 2000 milliseconds (2 seconds). The first statement is animating calls to the function Uize.Node.setOpacity, while the second statement is animating calling the method setOpacity on the context Uize.Node. Now, the implementation of the Uize.Node.setOpacity static method does not use the this keyword, so the context that it is called on does not affect its execution. So, one may as well just animate the opacity using the fading a function call approach. As you can see, in such cases the Uize.Fade.fadeMethod method does not even produce the most concise code.

IMPORTANT

An exception to this rule would be certain class methods that behave differently, depending upon which class they're called on, or that modify or access properties specific to the class on which they're called. So, the following two examples would most certainly NOT be equivalent...

INCORRECT

Uize.Fade.fade (Uize.Widget.Bar.Slider.set,{value:0},{value:100},2000);

CORRECT

Uize.Fade.fadeMethod (Uize.Widget.Bar.Slider,'set',{value:0},{value:100},2000);

The first example will simply not work - period. That's because the Uize.Widget.Bar.Slider.set method needs a class as a context, and by using the Uize.Fade.fade method it will simply be called as a function - without a context. The approach using the Uize.Fade.fadeMethod method works, because the context Uize.Widget.Bar.Slider is specified using the first parameter and this context is remembered for when the set method is to be called. Admittedly, you're not likely to want to fade the setting of the value for a state property on a class, but this example at least illustrates the point.

In cases where you need to animate the calling of a particular method on a particular context, you can use the Uize.Fade.fadeMethod static method, as discussed in the section Fading a Method Call.

4.2.3. Fading Uize.Node Method Calls

The Uize.Fade.fade static method lets you animate calls to any arbitrary function, including static methods of the Uize.Node module that don't need to be called with Uize.Node as the context (see Fading Static Methods As Functions).

EXAMPLE

Uize.Fade.fade (Uize.Node.setValue,['testNode',0],['testNode',100],5000);

In the above example, a value will be faded between 0 and 100 over a period of 5000 milliseconds (5 seconds) and this value will be displayed in the DOM node with the id of 'testNode'. The Uize.Node.setValue method takes two arguments - the first for the DOM node, and the second for the value. Because the value of the first parameter is the same between the start value arguments array and the end value arguments array, its value is not interpolated and is always 'testNode'.

4.3. Fading a Method Call

There may be cases where you would like to animate the calling of a method - either on an instance or on a class.

Of course, in such cases, you could always use the generic Uize.Fade.fade static method for initiating a genertic fade and then specify an anonymous function as the update handler, and then your update function could call the method, relying on the fact that the context and method name are known in the enclosing scope of the anonymous function. Well, you could always do that, but you do not need to - the Uize.Fade.xFactory module implements a Uize.Fade.fadeMethod static method that does just the job.

EXAMPLE

Uize.Fade.fadeMethod (marquee,'set',{left:0,top:0},{left:100,top:100},2000);

The above example animates the position of a marquee widget (an instance of the Uize.Widget.Resizer.Marquee class) from 0,0 to 100,100 over a period of 2000 milliseconds (2 seconds). With the Uize.Fade.fadeMethod method, the first parameter is the context or object on which the method should be called, and the second parameter is the name of the method to call, or a reference to the function that implements the method.

If you had to write the above code using the generic Uize.Fade.fade method, it would be a bit longer, as follows...

Uize.Fade.fade (
  function (value) {marquee.set (value)},{left:0,top:0},{left:100,top:100},2000
);

4.3.1. Fading Static Methods

For fading static methods, it is not usually necessary to use the Uize.Fade.fadeMethod method.

This is explained in more detail in the section Fading Static Methods As Functions.

4.3.2. Specifying Method to Fade

When using the Uize.Fade.fadeMethod method, you have flexibility in how you specify the method you wish to fade.

The value for the second parameter of the Uize.Fade.fadeMethod method can be a string, being the name of the method to call, or a reference to the method's function. When specifying a function reference for this parameter, the reference can be accessed from the prototype of the class of the instance (if it is an instance method), or it can be referenced from the instance (if it is an instance method), or it can be accessed from the class (if it is a class method), or it may be a function that is not a method of the instance but that one would like to be called as though it were a method of the instance, such as an anonymous function or a method of some other class.

In the following example, where we wish to fade a call to the set instance method of the instance slider, any of the statements would do the trick...

EXAMPLE

// method specified using a string value
Uize.Fade.fadeMethod (slider,'set',{value:0},{value:100},2000);


// method specified by function reference, accessing it from the instance
Uize.Fade.fadeMethod (slider,slider.set,{value:0},{value:100},2000);


// method specified by function reference, accessed from instance's class' prototype
Uize.Fade.fadeMethod (slider,slider.Class.prototype.set,{value:0},{value:100},2000);


// method specified by function reference, accessed from instance's class' prototype
Uize.Fade.fadeMethod (
  slider,Uize.Widget.Bar.Slider.prototype.set,{value:0},{value:100},2000
);


// method is an anonymous function that is called on the instance as a method
Uize.Fade.fadeMethod (slider,function (value) {this.set ({value:value})},0,100,2000);

Naturally, the first statement of the above set is the most preferable, but who knows how you might get access to the method to be faded in your own code. This example simply illustrates that you have options, and flexibility.

4.4. Fading the value State Property

The Uize.Fade.fade static method that is implemented in the Uize.Fade.xFactory extension module supports special handling when the target of a fade is an instance of a Uize.Class subclass.

What does it mean to fade an instance? When an instance is specified in place of an update function when calling the Uize.Fade.fade method, this method fades the value of the specified instance's value state property. So, if the class of your instance implements a value state property, then you can use this convenient shorthand. Consider the following example...

EXAMPLE

Uize.Fade.fade (slider,0,100,2000);

In the above example, slider is an instance of the Uize.Widget.Bar.Slider class, and this class has a value state property. So, the statement will have the effect of fading the value of the slider widget from 0 to 100 over a period of 2000 milliseconds (2 seconds) - short 'n sweet. Of course, you could accomplish the same effect by fading a method call or by fading a state property, as in...

// fading the slider value by fading a method call
Uize.Fade.fadeMethod (slider,'set',{value:0},{value:100},2000);

// fading the slider value by fading a state property
Uize.Fade.fadeProperty (slider,'value',0,100,2000);

But, why would you want to write more code, if you could avoid it?

4.5. Fading a State Property

While the Uize.Fade.fade static method can be used for fading the value state property, fading a state property other than the value property can be accomplished using the Uize.Fade.fadeProperty static method.

EXAMPLE

Uize.Fade.fadeProperty (marquee,'width',10,100,2000);

In the above example, marquee is an instance of the Uize.Widget.Resizer.Marquee class. The statement will fade the value of its width state property from 10 to 200 over a period of 2000 milliseconds (2 seconds).

4.6. Fading Many State Properties

While the Uize.Fade.fadeProperty static method can be used for fading a state property, fading values for multiple state properties of an instance in a single fade can be accomplished using the Uize.Fade.fadeProperties static method.

EXAMPLE

Uize.Fade.fadeProperties (marquee,{width:10,height:10},{width:100,height:100},2000);

In the above example, marquee is an instance of the Uize.Widget.Resizer.Marquee class. The statement will fade its dimensions (ie. the values of its width and height state properties) from 10 x 10 to 100 x 100 over a period of 2000 milliseconds (2 seconds).

Now, for what it's worth, you could also accomplish the same effect using the Uize.Fade.fadeMethod method, as follows...

Uize.Fade.fadeMethod (marquee,'set',{width:10,height:10},{width:100,height:100},2000);

As you can see, using the Uize.Fade.fadeProperties method isn't that much shorter, so it's offered more as a semantic convenience - use whichever makes more sense to you.

4.6.1. Fading From Current Values

To fade state properties from their current values to new values, simply specify the value null for the Uize.Fade.fadeProperties method's propertiesStartValuesOBJ parameter, as in...

EXAMPLE

Uize.Fade.fadeProperties (marquee,null,{width:100,height:100},2000);

The above example fades the dimensions of marquee from the current dimensions to 100 x 100 over a period of 2000 milliseconds (2 seconds).

4.6.2. Fading Back To Current Values

To fade state properties from new values back to their current values, simply specify the value null for the Uize.Fade.fadeProperties method's propertiesEndValuesOBJ parameter, as in...

EXAMPLE

Uize.Fade.fadeProperties (marquee,{width:100,height:100},null,2000);

The above example fades the dimensions of marquee from 100 x 100 back to the current dimensions to over a period of 2000 milliseconds (2 seconds).

4.6.3. Mixed From / Back To Current

The Uize.Fade.fadeProperties method also supports fading certain state properties from their current values to new values, and other state properties from new values back to their current values - in the same fade process.

Basically, when specifying the values of state properties in either of the propertiesStartValuesOBJ or propertiesEndValuesOBJ parameters, specifying the value null for any property, or omitting that property when it is specified for the opposite end of the fade, will result in the current value of that property being used. Consider the following example...

Uize.Fade.fadeProperties (marquee,{width:100},{height:100},2000);

In the above example, the width of the marquee instance is being faded from 100 back to its current value, while the height is being faded from its current value to 100, over a period of 2000 milliseconds (2 seconds). Because a value is not specified for width in the propertiesEndValuesOBJ parameter, its current value is used as the end value. And because a value is not specified for height in the propertiesStartValuesOBJ parameter, its current value is used as the start value.

5. Animating CSS Style Properties

While the Uize.Fade.xFactory extension module provides factory static methods for easily initiating generic kinds of animations, the UIZE JavaScript Framework also provides features specifically to ease the animation of CSS style properties.

5.1. Arbitrary Properties

Many compelling effects can be achieved by animating the values of the wide array of CSS style properties that can be modified by JavaScript code.

Instead of having to cobble together more complex animations using multiple concurrent fades, the Uize.Fx.fadeStyle method lets you fade the values of any number of CSS style properties in a single fade - right off the bat. Consider the following example....

EXAMPLE

Uize.Fx.fadeStyle (
  'myNode',{left:0,top:0,width:10,height:10},{left:100,top:100,width:200,height:200},2000
);

In the above example, the DOM node with the id of 'myNode' is being moved and resized, starting from a position of 0,0 and a size of 10 x 10, and ending up at the position of 100,100 and a size of 200 x 200. If you contrast this code against the code shown in the example in the section Compound Value Interpolation, you'll notice that the convenient Uize.Fx.fadeStyle method makes things much more concise when it comes to animating CSS style properties.

5.2. Animating a Single CSS Style Property

Fading the value of one style property is just the same as fading the values for multiple - only there'll be just one property in the start and end value objects. Consider the following example...

EXAMPLE

Uize.Fx.fadeStyle ('myNode',{opacity:1},{opacity:0},2000);

In the above example, we are fading the opacity of the node with the id of 'myNode' from 1 to 0 over a period of 2000 milliseconds (2 seconds).

5.3. Key Features

The Uize.Fx.fadeStyle static method has the following key features...

Supports a Wide Variety of CSS Style Properties - The Uize.Fx.fadeStyle method supports fading values for the following CSS style properties: color, background, backgroundColor, borderColor, borderTopColor, borderRightColor, borderBottomColor, borderLeftColor, top, right, bottom, left, backgroundPosition, padding, paddingTop, paddingRight, paddingBottom, paddingLeft, margin, marginTop, marginRight, marginBottom, marginLeft, width, height, maxWidth, maxHeigh, borderWidth, borderTopWidth, borderRightWidth, borderBottomWidth, borderLeftWidth, fontSize, letterSpacing, wordSpacing, lineHeight, textIndent
Flexibility in Specifying Color Values - Because the Uize.Fx.fadeStyle method uses the Uize.Color object in its implementation, it provides all the flexibility in specifying color values for color CSS style properties that one gets when using the Uize.Color object.
Builds Upon Uize.Fade - Because the Uize.Fx.fadeStyle method ultimately uses the Uize.Fade class in its implementation, style fades initiated using this method can be further qualified by specifying additional fade properties (such as a curve property) in its optional fadePropertiesOBJ parameter.
Handles Quantization - The Uize.Fx.fadeStyle method takes care of quantization for CSS style properties whose values should be integers, such as position and dimension values measured in pixels.
From Current Values, Back To Current Values, and Mixed - The Uize.Fx.fadeStyle method supports fades that start from the current style property values - as derived from the DOM node - and fade to specified values, fades that start from specified values and fade back to the current values, and fades where some properties fade from current to specified values and other properties fade from specified values to current values.

5.4. Animating CSS3 Style Properties

At the time of writing, most of the style properties defined in the CSS Level 3 specification are not yet supported in the majority of Web browsers in use.

An exception to this is the opacity property, which is officially part of the CSS3 specification but has nevertheless been supported in a number of browsers for quite some time.

5.4.1. CSS3 Animation Support in Extension Modules

Because support for all CSS3 style properties is likely to take some time to become pervasive, support for these properties is not built directly into the base modules that support CSS animation in the UIZE JavaScript Framework - support is instead provided in the form of extension modules.

5.4.1.1. Animating Text Shadow

An example of CSS3 style property support through extension modules is the Uize.Fx.xShadows module, which supports fading all the properties of a box shadow or an arbitrary number of text shadows for DOM nodes.

Fading values for the box shadow or text shadows of DOM nodes can produce some spectacular effects, but such effects can be considered esoteric enough that the weight of the framework should not be increased for the majority of use cases for the sake of supporting shadow animation. In cases where shadow animation is desired, it is easy enough to simply load the Uize.Fx.xShadows module.

5.4.1.2. Extension Module Support Benefits Many

Once an extension module that provides support for animating certain CSS3 style properties is loaded, then all modules that use the Uize.Fx module in their implementation will get the benefit of being able to animate the supported CSS3 style properties.

For example, after loading the Uize.Fx.xShadows module, the Uize.Widget.HoverFader widget class will support default and hover styles that contain text shadow and/or box shadow properties. Good demonstrations of this are the Hover Fader Text Shadow Animation and Animated Buttons with Box Shadow examples.

5.5. Advanced Techniques

The way that the Uize.Fx.fadeStyle method packs the values of all the style properties to be faded into compound start and end values, and the fact that it's possible to specify a compound value for the curve fade property, make some interesting techniques possible.

If you're fading multiple style properties in a single fade, the ability to specify a compound value for the curve fade property lets you specify different curve functions for different of the style properties being faded. Consider the following example....

EXAMPLE

Uize.Fx.fadeStyle (
  'myNode',
  {borderTopColor:'0',borderRightColor:'0',borderBottomColor:'0',borderLeftColor:'0'},
  {borderTopColor:'f',borderRightColor:'f',borderBottomColor:'f',borderLeftColor:'f'},
  3000,
  {curve:{
    borderLeftColor:Uize.Curve.Mod.band (1,.25,0),
    borderTopColor:Uize.Curve.Mod.band (1,.25,1/3),
    borderRightColor:Uize.Curve.Mod.band (1,.25,2/3),
    borderBottomColor:Uize.Curve.Mod.band (1,.25,1)
  }}
);

In the above example, we are fading the border color of the top, left, right, and bottom borders from black to white, over a period of 3000 milliseconds (3 seconds). When the fade has completed, the entire border will be white all around. However, because we're accomplishing this by fading the four discrete CSS border color properties, we get the ability to specify different curves for each using a compoung value for the curve fade property, whose value is an object with the same structure as the start and end values of the fade. There is an entry in the curve object for each of the style properties being faded. In this case, we're using the Uize.Curve.Mod.band curve function generator defined in the Uize.Curve.Mod module so that each of the borders' white "comes in" at different points in the fade. Because of the values we've used in this example, the border would fade to white in a clockwise fashion, starting from the left border.

5.5.1. Color Component Curves

The way that the Uize.Fx.fadeStyle method resolves color values to tuples that make their way into the compound start and end values of a style fade allows us to specify different curve functions for the different components of a color.

This provides a way to achieve subtle color transitions, where your start and end colors are always simple, but the colors that are faded through in the course of a fade produce elegant effects. Consider the following example...

EXAMPLE

Uize.Fx.fadeStyle (
  'myNode',
  {borderColor:'0'},
  {borderColor:'f'},
  3000,
  {curve:{
    borderColor:[
      Uize.Curve.Mod.band (1,.4,0),
      Uize.Curve.Mod.band (1,.4,.5),
      Uize.Curve.Mod.band (1,.5,1)
    ]
  }}
);

In the above example, the entire border is being faded from black to white over a period of 3000 milliseconds (3 seconds). We're specifying a curve fade property, with a value for the borderColor style property. Because we know that the Uize.Fx.fadeStyle method resolves a color style property value into a tuple array, we can specify an array for the borderColor curve, where each element of the array is a different curve function.

Fading the different components of the color along different curves through the course of the fade will result in the color not fading from black to white through various shades of gray, but instead producing different color tones along the way. In this example, the curves specified would produce the effect of the border color transitioning through hot colors before settling at pure white at the end. This is because the three band curves are making the red transition biased towards the start, green sitting in the middle, and blue biased towards the end. So, you see more red in the border color initially, and then it "cools off" as it approaches white.

5.5.1.1. Color Component Curves in Action

A good example of color component curves in action is the Hover Fader Color Effects example.

This example demonstrates how the Uize.Widget.HoverFader class (which uses the Uize.Fx.fadeStyle method in its implementation) can be used to create stunning menu animation effects that employ non-linear color transitions.

CHECK IT OUT

5.6. More Info on Uize.Fx.fadeStyle

For more info on the Uize.Fx.fadeStyle static method, consult the reference for the Uize.Fx module.

6. Curves

6.1. Linear is Boring

Let's face it: linear is boring. And besides, it's just not how the real world behaves.

To add some pizazz to animations, The UIZE JavaScript Framework provides modules that let you stray from the bland world of linear animations and into an exotic world of animations driven by arbitrary curve functions, with built-in support for easing curves as well as curves that emulate the complex properties of motion, letting you achieve effects like bounce, springiness, wobble, elasticity, etc. Beyond the built-ins, you have the freedom to roll your own curve functions in order to achieve some of the craziest motion effects you could imagine.

6.2. Check Out Those Curves!

To get an idea of what curves are all about, why not check out a few examples...

Curve Explorer - Provides a UI for visualizing and experimenting with curve functions, letting you select from a large number of preset curves in its "PRESETS" tab, and letting you see the curve expression and modify it to produce new curves.
Hover Fader Stretching Menu - Demonstrates how the Uize.Widget.HoverFader widget class can be used to create a stretching menu effect.

6.3. A Simple Curve Example

Before getting into the juicy details of curves and the powerful concepts surrounding them, consider the following simple example to whet your appetite...

EXAMPLE

Uize.Fx.fadeStyle (
  'myNode',                                 // node
  {left:0,top:0,width:10,height:10},        // start style properties
  {left:100,top:100,width:200,height:200},  // end style properties
  2000,                                     // duration
  {curve:Uize.Curve.easeInOutPow (4)}       // extra fade properties
);

In the above example, the DOM node with the id of 'myNode' is being moved and resized, starting from a position of 0,0 and a size of 10 x 10, and ending up at the position of 100,100 and a size of 200 x 200. Because the Uize.Fx.fadeStyle static method of the Uize.Fx module allows fade properties to be specified in its optional fadePropertiesOBJ parameter, a value can be specified for the curve state property of the Uize.Fade instance that will be used to service the style fade. In this case we're using the Uize.Curve.easeInOutPow static method of the Uize.Curve module to create a quartic (power of four) ease-in-out curve function. This will produce a transition that starts out slowly, picks up speed, and then slows down to end slowly.

6.4. Important Concepts

The UIZE JavaScript Framework introduces the following key concepts...

Curve Functions - functions that generate values for curves.
Curve Function Generators - functions or methods that generate curve functions, possibly accepting parameters that affect the generated curve functions.
Curve Function Modifiers - function or methods that accept curve functions as parameters and that generate modified versions of the source curve functions.

6.5. Curve Functions

In the UIZE JavaScript Framework, a curve is represented simply as a function that accepts a floating point number in the scale 0 to 1 and returns a value, also in the scale of 0 to 1, that reflects how that input value is distorted by the curve.

6.5.1. An Example

To illustrate the principle of a curve function, let's consider a simple example...

EXAMPLE

function cubicEaseOut (value) {
  value = 1 - value;
  return 1 - value * value * value;
}

The above curve function represents a cubic easing out curve, where change in the output value will occur rapidly at the beginning of the curve and then more slowly towards the end, so that there would be easing out of a fade effect that used this curve.

This curve is actually just a 180 degree rotated version of a cubic easing in curve, which would simply return the input value raised to the power of three. In order to rotate that curve 180 degrees, the curve is flipped both horizontally and vertically. It is flipped horizontally first by complementing the input value (subtracting it from 1). Then, the value is raised to the power of three. Finally, the cubed value is complemented in order to vertically flip the cubic curve.

The table of values below compares some sample input values with the output values that our cubicEaseOut function would produce...

INPUT VALUE   |   OUTPUT VALUE
-----------------------------------
1             |   1
.9            |   .999
.8            |   .992
.7            |   .973
.6            |   .9359999999999999
.5            |   .875
.4            |   .784
.3            |   .657
.2            |   .4879999999999999
.1            |   .2709999999999999
0             |   0

Looking at this table, what you'll notice first is that the function - while now producing non-linear output values - still produces values in the range of 0 to 1, where the input value 0 produces the output value 0 and the input value 1 produces the output value 1. Notably, the difference in output values for the input values of 0 and .1 is much greater than the difference in output values for the input values of .9 and 1. In other words, change is much faster at the beginning of the curve than it is at the end of the curve. This is the "easing out" quality that was mentioned earlier.

6.5.2. Definition

A curve function should comply with the following simple requirements...

6.5.2.1. Single Argument

A curve function must accept a single argument, being a floating point number in the scale 0 to 1.

6.5.2.2. Return Value

A curve function must return a floating point number in the scale 0 to 1.

6.5.2.3. May Produce Overshoot

A curve function may return a number outside of the range of 0 to 1.

Returning values outside of the range of 0 to 1 is useful for producing overshoot or back effects - particularly compelling for curves that emulate motion effects like bounce, springiness, wobble, elasticity, etc.

6.5.2.4. Should Handle Overshoot

A curve function should support input values outside the range of 0 to 1.

A curve function should be able to handle input values that were generated from some other curve function that used overshoot to achieve motion effects like bounce, springiness, wobble, elasticity, etc.

6.5.2.5. Start At 0, End At 1

A curve function should start at 0 (ie. the input value 0 should produce the output value 0) and end at 1 (ie. the input value 1 should produce the output value 1).

Curve functions that produce curves that start at the value 0 and end at the value 1 can be rotated 180 degrees to produce new curves that still start at 0 and end at 1. The rotated version of an ease-in curve function would produce an ease-out curve function. Similarly, the rotated version of an ease-out curve function would produce an ease-in curve function.

6.5.2.6. Deterministic

Ideally, a curve function should be deterministic (ie. it should always return the same output value for the same input value), although this is not a hard requirement.

Curve functions that are computationally complex can be sampled in order to improve performance, so that complex computations aren't performed repeatedly during peformance intensive animation effects. If a curve function is non-deterministic, then it will become deterministic as a result of being sampled. If apparent randomness or noise is desired in a curve, it is better to add it using a deterministic algorithm.

6.6. Using Curve Functions

Curve functions can be used in a wide variety of applications.

VISUALIZE IT

To better visualize how curve functions work and how they affect motion, visit the interactive Curve Explorer tool.

6.6.1. Blending Values

A curve function can be supplied as a parameter to the Uize.Math.Blend.blend static method of the Uize.Math.Blend class.

When not specifying a curve to this method, the interpolation used to blend between the two specified values is linear. Specifying our own curve allows us to perform non-linear blending.

EXAMPLE

var
  bouncyCurveFunction = Uize.Curve.Rubber.easeOutBounce (4,2),
  middleOfBounceValue = Uize.Math.Blend.blend (
    0,                   // value A
    255,                 // value B
    .5,                  // blend amount (.5 is halfway)
    0,                   // quantization (0 == none)
    bouncyCurveFunction  // curve function
  )
;

After the above code has executed, the middleOfBounceValue variable would be left with the value 90.4438142188662.

6.6.2. Curve Functions Are Not Blenders

Curve functions are not blenders, so they can't alone be used to blend between two different values.

Curve functions simply remap a value in the scale of 0 to 1 to a new value in the scale of 0 to 1. This reduces the burden on the implementation of curve functions, as they don't all have to deal with the math to blend between values. Additionally, not performing blending in a curve function improves performance when multiple curve functions are combined together to form more complex curve functions, using the curve function modifier methods defined in the Uize.Curve.Mod module.

All this said, it is quite easy to use a curve function to blend between values, as shown in the section Blending Values. Furthermore, blender functions can be composed from curve functions by using the convenient Uize.Curve.makeBlender static method of the Uize.Curve module, as shown in the following example...

EXAMPLE

var
  bouncyCurveFunction = Uize.Curve.Rubber.easeOutBounce (4,2),
  bouncyBlender = Uize.Curve.makeBlender (bouncyCurveFunction),
  middleOfBounceValue = bouncyBlender (0,255,.5)
;

After the above code has executed, the middleOfBounceValue variable would be left with the value 90.4438142188662. Now, every time that you use the bouncyBlender function to blend between two values, it will blend the values using the curve function generated by the statement Uize.Curve.Rubber.easeOutBounce (4,2).

6.6.3. Controlling Fades

A curve function can be supplied to an instance of the Uize.Fade class by setting the value of its curve state property, in order to control the characteristics of the fade's transition.

When not specifying a curve to a Uize.Fade instance, the fade's transition will be linear in nature. In other words, the rate of change will remain constant throughout the fade process. Specifying our own curve allows us to make the fade non-linear in order to emulate motion effects like bounce, springiness, wobble, elasticity, etc.

EXAMPLE

var positionFade = Uize.Fade ({
  startValue:{left:0,top:0},
  endValue:{left:100,top:100},
  duration:2000,
  quantization:1,
  curve:Uize.Curve.easeInOutPow (4)
});
positionFade.wire (
  'Changed.value',
  function () {Uize.Node.setStyle ('myNode',positionFade.get ('value'))}
);
positionFade.start ();

Although there are more concise ways of animating CSS style properties in order to fade the position of a node, the above example illustrates how a curve function can be specified as a value for the curve state property of an instance of the Uize.Fade class.

6.6.4. Controlling Effects

Because curve functions are supported by the Uize.Fade class, any modules that use instances of this class to drive fade effects can also use curve functions and permit curve functions to be used.

6.6.4.1. The Uize.Fade.xFactory Module

The various static methods defined in the Uize.Fade.xFactory extension module allow a curve function to be specified in the optional fadePropertiesOBJ parameter.

EXAMPLE

Uize.Fade.fade (scrollTo,[0,0],[0,200],800,{curve:Uize.Curve.easeInOutPow (4)});

6.6.4.2. The Uize.Fx Module

The Uize.Fx.fadeStyle static method of the Uize.Fx module allows a curve function to be specified in its optional fadePropertiesOBJ parameter.

EXAMPLE

Uize.Fx.fadeStyle (
  'myNode',                                 // node
  {left:0,top:0,width:10,height:10},        // start style properties
  {left:100,top:100,width:200,height:200},  // end style properties
  2000,                                     // duration
  {curve:Uize.Curve.easeInOutPow (4)}       // extra fade properties
);

6.6.4.3. The Uize.Widget.HoverFader Class

The Uize.Widget.HoverFader widget class allows a curve function to be specified in its fadeIn and fadeOut state properties.

EXAMPLE

page.addChild (
  'hoverFader',
  Uize.Widget.HoverFader,
  {
    defaultStyle:{width:150,letterSpacing:2,borderRightColor:'0'},
    hoverStyle:{width:240,letterSpacing:9,borderRightColor:'f'},
    fadeIn:{duration:1200,curve:Uize.Curve.Rubber.easeOutElastic (.2)},
    fadeOut:{duration:1000,curve:Uize.Curve.Rubber.easeOutBounce (5,-2,1.5)}
  }
);

6.6.4.4. Other Widget Classes

Some widget classes - such as the Uize.Widget.ImageWipe class, and the Uize.Widget.Swap class and its subclasses - use an instance of the Uize.Fade class to drive their animation.

Typically this fade instance will be created during construction of an instance of the widget class, and will be publicly accessible via a fade instance property. For such classes, a curve function can be set on the fade instance immediately after creation of the widget instance, as shown in the example below...

EXAMPLE

var myImageWipe = page.addChild ('imageWipe',Uize.Widget.ImageWipe,{built:false});

myImageWipe.fade.set ({curve:Uize.Curve.easeInOutPow (4)});

6.6.5. Just About Anywhere

Because curve functions are so elementary, they can really be used anywhere where you'd like to work with scaling values.

6.7. Curve Function Generators

A curve function generator is a function or method that generates a curve function as its output.

Examples of curve function generators are the various static methods contained inside the Uize.Curve module, the Uize.Curve.Rubber module, as well as the various curve function modifier methods contained inside the Uize.Curve.Mod module. As stated, the result returned by a curve function generator is a curve function that can be used anywhere that you would use a curve function, such as with instances of the Uize.Fade class, or with animation effects initiated by methods of the Uize.Fx module.

6.7.1. Parameterized Curve Function Generators

Curve function generators can either take no parameters, or they can be parameterized.

6.7.1.1. Examples

Examples of parameterized curve function generators include some of the static methods of the Uize.Curve module (such as the various power and circular curve function generators), static methods of the Uize.Curve.Rubber module (such as the bounce, back, and elastic curve function generators), as well as the curve function modifier static methods of the Uize.Curve.Mod module.

EXAMPLE

var
  superBouncyEaseOut = Uize.Curve.Rubber.easeOutBounce (9,4,1.25),
  muffledBounceEaseOut = Uize.Curve.Rubber.easeOutBounce (3,-4,1.7)
;

After the above code has executed, the values of superBouncyEaseOut and muffledBounceEaseOut are two different curve functions, each one observing the parameters specified when creating it by calling the Uize.Curve.Rubber.easeOutBounce static method.

6.7.1.2. No Muss, No Fuss

Because parameterized curve function generators simply return curve functions, the burden is taken off of other code for passing values for the parameters that only shape a curve - a curve's shape can be defined once when creating its curve function.

In this way, all that the user of the resulting curve function has to do is supply a value in the scale 0 to 1 to it, and the curve function returns the corresponding value at that point on the curve.

6.7.1.3. Memoization

As an optimization, curve function generators can return a reference to the same underlying curve function each time they are called with identical parameter values.

However, a parameterized curve function generator must always return a curve function that is unique to its parameter values.

EXAMPLE

Uize.Curve.easeOutPow () == Uize.Curve.easeOutPow ()    // true
Uize.Curve.easeOutPow (3) == Uize.Curve.easeOutPow (3)  // false

As it's implemented, the statement Uize.Curve.easeOutPow () always returns a reference to the same quadratic ease-out curve function. However, the statement Uize.Curve.easeOutPow (3) always returns a new curve function - even for identical values of the powerFLOAT parameter.

As an additional optimization, you could choose to implement memoization for parameterized curve function generators. The parameterized curve function generators in the Uize.Curve and Uize.Curve.Rubber modules are not memoized, but those that are called without parameters always return a reference to the same shared curve function.

6.7.2. Easing Equations

An easing equation is an equation used to produce a special type of curve function - one that produces the effect of easing into, easing out of, easing into and out of, or easing in the middle of a transition.

6.7.2.1. Credit Where Credit Is Due

Thanks go to Robert Penner for his work on his easing equations, which provided a starting point and inspiration for work that has been done in the Uize.Curve module and related modules.

In some cases, his original methods have merely been refactored, such as with the Uize.Curve.Rubber.easeInElastic method and related elastic easing curve function generators provided in the Uize.Curve.Rubber module. In other cases, the original implementations have been completely replaced, such as with the Uize.Curve.Rubber.easeInBounce method and related bounce easing curve function generators provided in the Uize.Curve.Rubber module, with the new implementation being much more versatile than the original. Either way, his excellent work has been an inspiration.

6.7.2.2. Ease-in Curve Function

Easing into a transition means that the rate of change will be slow at first and then progressively accelerate. This will produce an effect that starts gently.

6.7.2.3. Ease-out Curve Function

In contrast, easing out of a transition means that the rate of change will slow towards the end, progressively decelerating as the transition approaches the end point. This will produce an effect that ends gently.

An ease-out curve function is actually just a 180 degree rotated version of an ease-in curve function. In order to rotate the ease-in curve 180 degrees, the curve is flipped both horizontally and vertically. It is flipped horizontally first by complementing the input value (subtracting it from 1). Then, the value is remapped using the ease-in curve function. Finally, the remapped value is complemented in order to vertically flip the already horizontally flipped curve.

An ease-out curve function can be generated from a source ease-in curve function using the Uize.Curve.makeEaseOut static method of the Uize.Curve module, as follows...

var myEaseOutCurveFunction = Uize.Curve.makeEaseOut (myEaseInCurveFunction);

6.7.2.4. Ease-in-out Curve Function

Easing into and out of a transition means that the rate of change will be slow at the beginning and end of the transition, and will then be higher inbetween in order to make up. This will produce an effect that starts and ends gradually.

An ease-in-out curve function is the combination of a source ease-in curve function occupying the bottom left quadrant, flowing into the 180 degree rotated version of that source ease-in curve function occupying the top right quadrant, producing a seamless curve that flows from the bottom left to the top right.

An ease-in-out curve function can be generated from a source ease-in curve function using the Uize.Curve.makeEaseInOut static method of the Uize.Curve module, as follows...

var myEaseInOutCurveFunction = Uize.Curve.makeEaseInOut (myEaseInCurveFunction);

6.7.2.5. Ease-in-the-middle Curve Function

Easing in the middle means that the rate of change will be fast at the beginning and end of the transition, but will be slower in the middle. This will produce an effect that starts abruptly and ends abruptly, and appears to pause / ease during the middle.

An ease-in-the-middle curve function is the combination of the 180 degree rotated version of a source ease-in curve function occupying the bottom left quadrant, flowing into that source ease-in curve function occupying the top right quadrant, producing a seamless curve that flows from the bottom left to the top right.

An ease-in-the-middle curve function can be generated from a source ease-in curve function using the Uize.Curve.makeEaseMiddle static method of the Uize.Curve module, as follows...

var myEaseMiddleCurveFunction = Uize.Curve.makeEaseMiddle (myEaseInCurveFunction);

6.7.2.6. Easing Curve Function Generators

The Uize.Curve module provides a number of the more commonly used curve function generators as built-ins.

This includes curve function generators such as Uize.Curve.easeInPow, Uize.Curve.easeOutPow, Uize.Curve.easeInOutPow, Uize.Curve.easeInCircular, Uize.Curve.easeOutCircular, etc. Additionally, a number of curve function generators that emulate motion effects like bounce, springiness, wobble, elasticity, etc. are provided in the Uize.Curve.Rubber module.

NAMING CONVENTION

The naming convention for the easing curve function generators is that the ease-in curve function generators start with the prefix "easeIn", the ease-out curve function generators start with the prefix "easeOut", the ease-in-out curve function generators start with the prefix "easeInOut", and the ease-in-the-middle curve function generators start with the prefix "easeMiddle".

6.7.2.7. Making Easing Curve Function Generators

Static methods for generating easing curve functions can be manufactured by calling the Uize.Curve.makeEasingCurveGenerators static method of the Uize.Curve module and providing a curve generator function for the ease-in curve function version.

EXAMPLE

Uize.Curve.makeEasingCurveGenerators (
  'Power',
  function (power) {
    if (power == null) power = 2;
    return function (value) {return Math.pow (value,power)};
  }
);

The above example would create the four curve generator static methods Uize.Curve.easeInPower, Uize.Curve.easeOutPower, Uize.Curve.easeInOutPower, and Uize.Curve.easeMiddlePower. For a more detailed discussion, consult the reference for the Uize.Curve.makeEasingCurveGenerators method.

6.8. Curve Function Modifiers

Curve function modifiers are curve function generators that accept curve functions as their primary inputs.

The Uize.Curve.makeEaseOut, Uize.Curve.makeEaseInOut, and Uize.Curve.makeEaseMiddle static methods of the Uize.Curve module can be considered curve function modifiers, because they take a curve function as an input and return a modified curve function as an output. Additionally, a good selection of more exotic curve function modifiers are provided in the Uize.Curve.Mod module.

Curve function modifiers operate on the curve functions they are provided in order to produce new, modified curve functions. You can consider them as operators that operate on curve functions to produce new curve functions. They could also be thought of as specialized parameterized curve function generators, where some - or all - of the parameters just happen to be curve functions. As an example, the Uize.Curve.Mod.blend static method blends the two specified curve functions to produce a new curve function, with blend parameters that let you specify the blend between the two curve functions.

"What does it mean to blend two functions?" you may ask. No, JavaScript doesn't support some crazy new math that allows us to add or multiply functions. Blending two curve functions is carried out by returning a new curve function that takes an input value, uses each of the two curve functions that are to be blended and obtains a remapped value from each, then blends between those two values to produce a new output value. This has the effect of blending the curves that would be produced by the two curve functions that are being blended - across their entire input value range. So, effectively, you are blending two curve functions to produce a new curve function.

EXAMPLE

// quickly to middle, hesitate, quickly to end

Uize.Curve.Mod.blend (
  Uize.Curve.easeInSweetPow (1/6),
  Uize.Curve.easeOutSweetPow (1/12),
  Uize.Curve.line (0,1)
)

In the above example, the curve function generated by the statement Uize.Curve.easeInSweetPow (1/6) is being blended with the curve function generated by the statement Uize.Curve.easeOutSweetPow (1/12), with the blend biased towards the first curve function at the lower input values, and biased towards the second curve function at the higher input values.

VISUALIZE IT

To better visualize how curve function modifiers work and how they affect motion, visit the interactive Curve Explorer tool.