You are here: Overview > Widget Animation Using Flex Forms > Animation Limitations > Keyframe Animation

Widget Animation Using Flex Forms

Kony widgets provide your app with the ability to animate widgets placed in a container such as a Form. To animate a widget means to move it, rotated it, and so forth. Your app can perform transformation, rotation, and scaling operations on widgets to move them, rotate them, or make them larger or smaller. Your app can perform both 2D and 3D animations. The 2D animations are supported on iOS, Android, Windows, and SPA platforms and the 3D animations are supported on iOS, SPA and Android.

The directions used for animations are as follows.

Animations take time for the user's device to perform. As a result, your app should not change a widget's properties immediately after initiating an animation. Because the animation may still be in progress, your app should wait to change the properties of widgets until after it is sure that the animation has completed.

To download a sample app to view the animations, click here.

Keyframe Animation

The most basic type of widget animation is called keyframe animation. Using keyframe animation, your all can specify specific transformations that happen at specific locations. For example, your all could specify that a Label widget moves +5 in the y direction, then move -6 in the x direction, and then rotate 90 degrees. Each of these three steps can be performed by specifying three key frames. In the case of this example, the Label widget "knows" how to fill in the intermediate step between each of the three key frames, if you give it the correct input.

When your app perform s keyframe animation, it must define the key frames to use in an animation definition object. The animation definition object is a JavaScript object that your app creates and passes to the kony.ui.createAnimation function. The sample code below illustrates how to create and use an animation definition object.

var animDefinition = {
    "0": {
        "top": "0dp",
        "left": "0dp"
    },
    "100": {
        "top": "50dp",
        "left": "50dp"
    }
};
animDef = kony.ui.createAnimation(animDefinition);

As the example shows, the animation definition object contains key-value pairs. The keys are integer percentages ranging from 0 to 100 inclusive. A key of 0 specifies the point at which 0% of the animation is complete. In other words, the 0 key is for the very start of the animation. Likewise, a key of 100 selects the point at which the animation is 100% completed, or the end of the animation sequence.

The values for each key in the animation definition objects are themselves JavaScript objects containing key-value pairs. For more information on the supported keys, see the documentation for the kony.ui.createAnimation function. In the example above, the keys used are "top" and "left", which specify the location of the top left corner of the widget being animated. The example shows the widget starting with its upper left corner at 0,0, relative to its container, at the start of the animation. By the time the animation finishes, the widget's upper left corner is located at 50,50. The widget's animate method uses these key frames and fills in everything in between.

After your app builds an animation definition object, it must create a animationConfiguration object. For more information on animation configuration, please see the AnimationConfiguration object documentation in the Kony Visualizer API Developer's Guide.

function animConfig() {
    var config = {
        "duration": 1,
        "iterationCount": 1,
        "delay": 0,
        "fillMode": kony.anim.FILL_MODE_FORWARDS
    };
    return config;
}

Finally, your app calls the widget's animate method to perform the animation.

FormAnimation.widgetAnimation.animate(animDef, animConfig);

Affine Transform Animation

Your app performs affine transform animations by first calling the kony.ui.makeAffineTransform function to create a transform object. Your app then calls the methods of the transform object, such as rotate, scale, and translate, to set transformations to be performed. Your app can set as many transformations on the transform object as it needs to. The example below illustrates how this is done.

// Creates a transformation object that can be used in an animation definition. 
var transformObject = kony.ui.makeAffineTransform();

// Add a translation and a scale.					
transformObject.translate(10, 0);
transformObject.scale(0.1, 1);

The transform object is then used inside of an animation definition, as shown in the following sample code.

// Create the animation definition.			
animationDef = {
    "100": {
        "transform": transformObject
    }
};

The animation definition is a JavaScript object containing key-value pairs. The keys specify the percentage of the completed animation. So 0 selects the start of the animation and 100 selects the end.

Animations require an animation configuration. For more information on animation configuration, please see the AnimationConfiguration object documentation in the Kony Visualizer API Developer's Guide.

//Create the animation configuration.
animationConfig = {
    "duration": 0.3,
    "fillMode": kony.anim.FILL_MODE_FORWARDS
};

After creating the transform object, the animation definition, and the animation configuration, your app must call the kony.ui.createAnimation function to create an animation object. When it does, it must pass the animation definition, which contains the transform object, to the kony.ui.createAnimation function as a parameter, as the following code example shows.

// Creates an object that defines an animation.
animationDefObject = kony.ui.createAnimation(animationDef);

At this point, the animation object is created and has a specific set of transformations associated with it. Your app can use the animation object to animate any flexform-based widget. To do so, it calls the widget's animate method and passes the animation object in as a parameter. The code in the example below demonstrates this process.

FormAnimation.widgetAnimation.animate(animationDefObject, animationConfig);

Your app can combine key frame animation and affine transform animation in a sequence. For example, it could perform an affine transformation from 0% to 50%, followed by a simple key frame animation from 50% to 100%.

// Creates a transformation object that can be used in an animation definition. 
var transformObject = kony.ui.makeAffineTransform();

// Add a translation and a scale.					
transformObject.translate(10, 0);
transformObject.scale(0.1, 1);

// Create the animation definition.			
animationDef = {
    "0": {
        "top": "0dp",
        "left": "0dp"
    },
    "50": {
        "top": "50dp",
        "left": "50dp"
    }
    "100": {
        "transform": transformObject
    }
};

Other Animation Types

In addition to animating positional properties, such as top and left, your app can perform other types of animation. For example, it can change the background color, gradient color (if a gradient skin is set), or shadow color over time. It can also alter the border color and corner radius to perform animations on those properties. The exact list of widget properties that can be animated is as follows.

backgroundColor Animation

To perform a gradient animation for backgroundColor, use the following code:

// Gradient animation
var animDefinition = {
    "0": {
        "backgroundColor": {
            "angle": 0,
            "colors": ["909ffa", "fff000", "eef004"],
            "colorStops": [0, 50, 90]
        }
    },
    "50": {
        "backgroundColor": {
            "angle": 45,
            "colors": ["ea5075", "f1fa70", "eefd04"],
            "colorStops": [0, 90, 100]
        }
    },
    "100": {
        "backgroundColor": {
            "angle": 0,
            "colors": ["00ff00", "ff0000", "000000"],
            "colorStops": [0, 10, 30]
        }
    }
};

animDef = kony.ui.createAnimation(animDefinition);

var config = {
    "duration": 3,
    "iterationCount": 2,
    "delay": 0,
    "fillMode": kony.anim.FILL_MODE_FORWARDS
};

widgetAnimation.animate(animDef, config, null);

Note that:

Platform-specific limitations for gradient animations.

Windows

Gradient animations will not work on the following widgets:

Animations are not smooth as other platforms because of limitation of the Windows platform.

Shadow animations are not supported.

When borderWidth is applied to a container widget, subWidgets or Children may be clipped or overlapped depending on the layout type.

iOS:

Gradient animations will not work on the following widgets:

Android:

Gradient animations will not work for the following widgets:

Shadow animations are not supported.

Corner radius animation

//Corner radius animation
function cornerRadius() {
    var animDefinition = {
        "0": {
            "cornerRadius": 20
        },
        "50": {
            "cornerRadius": 25
        },
        "100": {
            "cornerRadius": 10
        }
    };
    animDef = kony.ui.createAnimation(animDefinition);
    var config = {
        "duration": 3,
        "iterationCount": 2,
        "delay": 0,
        "fillMode": kony.anim.FILL_MODE_FORWARDS
    };
    FormAnimation.widgetAnimation.animate(animDef, config, null);
};

Shadow color animation

Animating the shadow color would use code similar to the following example.

// Animating the shadow color.
widgetAnimation.animate(kony.ui.createAnimation({
    "100": {
        "stepConfig": {
            "timingFunction": kony.anim.EASE
        },
        "shadowColor": "ffeb3800"
    }
}), {
    "delay": 0,
    "iterationCount": 5,
    "fillMode": kony.anim.FILL_MODE_BACKWARDS,
    "duration": 1.5
}, {
    "animationEnd": animationCallbackFn
});

The following sample shows how to animate the shadow radius.

// Animating the shadow radius.
widgetAnimation.animate(kony.ui.createAnimation({
    "100": {
        "stepConfig": {
            "timingFunction": kony.anim.EASE
        },
        "shadowRadius": 3
    }
}), {
    "delay": 0,
    "iterationCount": 5,
    "fillMode": kony.anim.FILL_MODE_BACKWARDS,
    "duration": 1.5
}, {
    "animationEnd": animationCallbackFn
});

The next sample shows how to animate the shadow offset.

// Animating the shadow offset. 
widgetAnimation.animate(kony.ui.createAnimation({
    "100": {
        "stepConfig": {
            "timingFunction": kony.anim.EASE
        },
        "shadowOffset": {
            "x": 11,
            "y": -15
        }
    }
}), {
    "delay": 0,
    "iterationCount": 5,
    "fillMode": kony.anim.FILL_MODE_BACKWARDS,
    "duration": 1.5
}, {
    "animationEnd": animationCallbackFn
});

Parent/Child Widget Animations

If a parent widget is animated, it is typically desirable to animate the child widget that the parent contains. Recall that all widgets have positional properties that specify such things as the location of the widget's upper left corner. Your app can specify the values of these properties in a variety of unit types, such as dp, px, or percentages. If your app is going to animate a parent widget, it is strongly recommended that your app specify the values of location properties such top, left, right, and bottom for both the parent and the child in percentages. If it doesn't, the child widgets are not animated together with the parent.

More specifically, animations are not performed for parent and child properties that are not both specified in percentages. For example, if the parent's left property is specified in percentages and the child's isn't, the child's left property will not be animated because it won't change. Likewise, if the child's left property is specified in percentages and the parent's isn't, the child's left property isn't changed, so animations involving the left property are not done on the child widget.

Animations are Asynchronous

Animations occur asynchronously. When your app calls a widget's animate method, it returns immediately and continues executing program statements while the animation proceeds. So during the time animations are occurring, your app can produce undefined behavior if it allows users to interact with the widget or widgets being animated. It is wise to disable user input during widget animations.

Also, layout events cannot be guaranteed to occur synchronously with specific key frames. If the widget your app is animating has a doLayout callback, undefined behavior may result. It is wise for your app to disable layout events during animations.

Your app can initiate multiple animations that run in parallel by simply calling the animate method on multiple widgets one after the other. There are specific caveats, however. The widgets being animated at the same time cannot share a parent/child relationship. They must also not be siblings inside a HORIZONTAL_FLOW or VERTICAL_FLOW container.

Attempting to perform parallel animations on the same widget can cause undefined behavior, as can canceling an animation that is currently in progress.

To sequence the animations one after the other, animation events have to be used. You can start a new animation at the end of the existing animation using animationEnd event. For more information, see the documentation for the animationCallbacks parameter of the animate method of the widget your app is animating.

Animation Limitations

Following are the limitations applicable to iOS, Android, SPA, and Windows platforms using widget level animations:

Animation Limitations Using Flex Layout

Animation Limitations on iOS

Animation Limitations on Android

Animation Limitations on Windows

Animation Limitations on SPA

Animation Limitations on Desktop Web

prem Copyright © 2012 Kony, Inc. All rights reserved.
prem Copyright © 2012 Kony, Inc. All rights reserved.