Creating Sophisticated Animations with the Microsoft AJAX Library

The AnimationExtender control in the ASP.NET AJAX Control Toolkit makes it easy to add animated effects to Web pages. I especially like the fact that you can compose complex animations from simple animations and use <Parallel> and <Sequence> elements to control animation order.

Much of AnimationExtender’s magic is found in a file named Animations.js, which is derived from PreviewGlitz.js in the ASP.NET AJAX Futures January CTP. I was curious to find out how difficult it would be to implement complex animations using the low-level animation classes in PreviewGlitz.js, and found that there are virtually no samples out there demonstrating how to perform anything but the most trivial animations. So I cracked open the file and went spelunking. The result is my “Balloon Pop” demo (pictured below), which you can download here. When you click a balloon, the balloon pops. The pop is really a series of animations run in parallel to simultaneously fade the balloon out and scale its width and height from 1 to 8. Once the animations are complete, a bit of JavaScript code deletes the balloon by removing the balloon image from the browser DOM.

For comparison, here’s how the animation would be implemented using the ASP.NET AJAX Control Toolkit’s AnimationExtender:

<asp:Image id=”Balloon1″ ImageUrl=”~/Images/balloon.gif” runat=”server”
style=”position: absolute; left: 320px; top: 260px; width: 74px; height: 110px” />
<ajaxToolkit:AnimationExtender ID=”AnimationExtender1″ TargetControlID=”Balloon1″ Runat=”server”>
<Animations>
<OnClick>
<Sequence>
<Parallel Duration=”0.2″ Fps=”40″>
<Scale ScaleFactor=”8″ Center=”true” />
<FadeOut />
</Parallel>

function removeBalloon(id)
{
var image = $get(id);
image.parentNode.removeChild(image);  // Remove the image
}

 

It’s more difficult using the animation classes in PreviewGlitz.js. There is no equivalent of AnimationExtender’s <Parallel> element, so you create a Sys.Preview.UI.Effects.CompositeAnimation object and encapsulate all the subanimations inside it. I used NumberAnimations to simultaneously animate the width, height, x-position, and y-position of the balloon, plus a FadeAnimation to fade it out. (Makes you appreciate AnimationExtender’s ScaleAnimation, doesn’t it?) Once the CompositeAnimation has run its course, a bit of JavaScript needs to be executed to remove the balloon image from the DOM. At first glance, it appears that you can register a handler for the end event that fires when the animation is complete. However, in what is probably an oversight in the January CTP, PreviewGlitz.js’s animation classes don’t fire end events. So I set up a timer to check the animation progress and remove the image from the DOM after the animation ends. Not pretty, but it works.

Here is the key source code:

<img id=”Balloon1″ src=”Images/balloon.gif” > style=”position: absolute; left: 320px; top: 260px; width: 74px; height: 110px” />

var _scaleFactor = 8; // Modify this number to change the scale factor
var _image, _animation;

function popBalloon(id)
{
if (_animation != null)
return; // Prevent overlapping animations
_image = $get(id);
var width = parseFloat(_image.style.width);
var height = parseFloat(_image.style.height);
var x = parseFloat(_image.style.left);
var y = parseFloat(_image.style.top);
//
// Use a CompositeAnimation object to “explode” the image by
// simultaneously scaling, moving, and fading it.
//
var a1 = new Sys.Preview.UI.Effects.NumberAnimation();
a1.set_target(_image);
a1.set_property(‘style’);
a1.set_propertyKey(‘width’);
a1.set_startValue(width);
a1.set_endValue(width * _scaleFactor);
var a2 = new Sys.Preview.UI.Effects.NumberAnimation();
a2.set_target(_image);
a2.set_property(‘style’);
a2.set_propertyKey(‘height’);
a2.set_startValue(height);
a2.set_endValue(height * _scaleFactor);
var a3 = new Sys.Preview.UI.Effects.NumberAnimation();
a3.set_target(_image);
a3.set_property(‘style’);
a3.set_propertyKey(‘left’);
a3.set_startValue(x);
a3.set_endValue(x – (width * (_scaleFactor – 1)) / 2);
var a4 = new Sys.Preview.UI.Effects.NumberAnimation();
a4.set_target(_image);
a4.set_property(‘style’);
a4.set_propertyKey(‘top’);
a4.set_startValue(y);
a4.set_endValue(y – (height * (_scaleFactor – 1)) / 2);
var a5 = new Sys.Preview.UI.Effects.FadeAnimation();
a5.set_target(new Sys.Preview.UI.Image(_image));
a5.set_effect (Sys.Preview.UI.Effects.FadeEffect.FadeOut);
_animation = new Sys.Preview.UI.Effects.CompositeAnimation();
_animation.get_animations().add(a1);
_animation.get_animations().add(a2);
_animation.get_animations().add(a3);
_animation.get_animations().add(a4);
_animation.get_animations().add(a5);
_animation.set_duration(0.2);
_animation.set_fps(40);
_animation.play();
//
// Because the animation classes in PreviewScript.js do NOT fire end
// events (even though you can register end handlers), manually set a
// timer to fire after 0.4 seconds so we can remove the image from the
// DOM once the animation is complete.
//
var timer = new Sys.Preview.Timer();
timer.initialize();
timer.set_enabled(true);
timer.set_interval(400);
timer.add_tick(removeBalloon);
}
function removeBalloon(sender)
{
if (!_animation.get_isPlaying())
{
sender.set_enabled(false);              // Disable the timer
_image.parentNode.removeChild(_image);  // Remove the image
_animation = null;
}
}

 

Understanding how to do animations with PreviewGlitz.js is more than academic. If you want to use ASP.NET AJAX to do animations on non-ASP.NET platforms such as PHP and ColdFusion, you can’t use the ASP.NET AJAX Control Toolkit because it’s ASP.NET-specific. But you can use PreviewGlitz.js. And now there’s an example to go by.

Jeff Prosise

View Comments

  • To a person who doesn't like much Javascript, u sure rule! :D Tks for the chat in TechDays, was a pleasure to meet u, and about this post? Nice... simply nice...

  • Jeff, have you taken a look at the client classes in the AJAX Toolkit? According to my sources, animation classes present on the toolkit are better than those you have on the preview bits and will get better support in the future (according to some, the preview classes will be fropped - including the drag-and-drop classes - and everything will be moved into the toolkit). The only problem I see with the toolkit client classes is that it's almost impossible to use only client code (ie, you need to drop the dll on the bin folder or you'll have to go through the client code and remove several references to elements which are inserted on the page by the dll on the server side)

  • Yes, I have looked at the ones in the toolkit. They're very similar to the ones in the CTP (but slightly better). I used the ones in the CTP because those are the ones that non-ASP.NET developers are supposed to use, although there's nothing preventing them from extracting the script resources from the toolkit assembly and using those.

  • Very cool! But it doesn't seem to work in Firefox. Any chance of making the code cross-browser-compatible? Or am I missing something?
    Thanks for a great class on Tues/Wed!

  • It should work in Firefox 2.0. I haven't tested it there, but if it doesn't work there, something's wrong because the Microsoft AJAX Library supports that platform. I'll check it out and see if something's missing.

  • Gee, you're right: it doesn't work in Firefox. The fade animation works, but the scaling does not. I wonder if this is because the animation classes are part of the CTP and not part of the core.
    Interestingly enough, I have a version of the same page that uses the toookit animation classes, and it works better in FireFox than it does in IE! I'll compare the JavaScript used by the toolkit animation classes to the JavaScript in PreviewGlitz.js to see what's different.

  • I noticed that the toolkit animation page worked in Firefox as well. The first time I tried the javascript page I only had the 1.0 release of ASP.NET AJAX installed. I thought maybe it wasn't working because I didn't have the CTP installed, so I downloaded and installed that as well. However, it didn't make a difference. Very odd indeed.

  • Jeff,
    I wonder if you've had any experience with the HoverExtender? I was really excited by this control but then found a serious bug. You can see it here: http://pocketpollster.com/beta/products.aspx
    Hover once and everything works fine. But slowly move the cursor in a 2nd time and you'll see that the hover is activated when you hit the extents or the LARGER image, not the original thumbnail.
    My intuition tells me that this is a bug that could be resolved by a fix in JavaScript but I don't know that language. :-(
    Anyhow, I was hoping you might know a solution.
    Robert Werner
    Vancouver, BC

Recent Posts

How to Navigate Azure Governance

 Cloud management is difficult to do manually, especially if you work with multiple cloud…

5 days ago

Why Azure’s Scalability is Your Key to Business Growth & Efficiency

Azure’s scalable infrastructure is often cited as one of the primary reasons why it's the…

3 weeks ago

Unlocking the Power of AI in your Software Development Life Cycle (SDLC)

https://www.youtube.com/watch?v=wDzCN0d8SeA Watch our "Unlocking the Power of AI in your Software Development Life Cycle (SDLC)"…

1 month ago

The Role of FinOps in Accelerating Business Innovation

FinOps is a strategic approach to managing cloud costs. It combines financial management best practices…

1 month ago

Azure Kubernetes Security Best Practices

Using Kubernetes with Azure combines the power of Kubernetes container orchestration and the cloud capabilities…

1 month ago

Mastering Compliance: The Definitive Guide to Managed Compliance Services

In the intricate landscape of modern business, compliance is both a cornerstone of operational integrity…

2 months ago