My recent Silverlight-related blog posts have shared a common theme: creating declarative views - whether it is declaratively attaching behaviors such as auto-complete, or declaratively hooking up views to their associated view models, or declaratively authoring themes and loading them. This post is the next installment in that overall series - declarative effects and transitions.
XAML and Silverlight provide some building blocks like storyboards and now visual state manager that enable some powerful mechanisms for adding visual pizzaz to your application's user interface. However, I sometimes find they are too general and low-level a solution, requiring one to go into custom template mode all too often, whether it is to define storyboards, or new states and transitions - more often than not, I just want a simple pre-packaged effect that I can attach to an element and associate with some user interaction. Furthermore, the current lack of event triggers requires code to be added to views to begin and stop those storyboards or switch from one visual state to another. Think powerpoint - the prepackaged animation effects with some basic triggers go a long way.
That sort of problem space, and approach inspired me to see what can be done in Silverlight today, resulting in the addition of a Glitz namespace in my Silverlight.FX work. (The name is no coincidence. For those that remember our Ajax framework's early days, back when it was called Atlas, I had written a Glitz script animation framework there, and then wrote one for Script# - this Silverlight work started its life when I recompiled my Script# code as actual managed code rather than into JavaScript!)
On the top is a set of screen-shots of a simple application that consumes some of these effects. You have to click it to run it live to actually see the effects! The application basically fetches the current weather and the forecast for the supplied zip code (and yes, it seems summer has decided to take a break here in the northwest). All the core logic is implemented in a view model that is decoupled from the view, and is easily tested. It is responsible for talking to the data layer, which is responsible for invoking a web service and unpacking the JSON data returned from the service. The view is completely declarative and is about 130 lines of XAML. It uses behaviors (for things like filtering zip code input to numbers), actions to hook into the view model, and of course effects and transitions for some subtle bits of glitz.
I'll share a couple of snippets of the XAML, just to get the general programming model across.
First is the Load button that not only instructs the view model to load weather for the supplied zip code, but also plays a transition to go from the initial screen to the next.
<fxui:Button Content="Load"
fxui:ButtonEvents.Click="$model.LookupWeather(zipCodeTextBox.Text)">
<fxglitz:Effects.ClickEffect>
<fxglitz:SlideTransition Mode="Left" TargetName="layoutGrid" Duration="00:00:1.25"
Reversible="False" Easing="ElasticInOut" />
</fxglitz:Effects.ClickEffect>
</fxui:Button>
Second, is an effect attached to the logical mouse hover event (which implies playing the effect in forward direction on mouse enter, and playing the same effect in reverse direction in response to the mouse out event) on the vertical forecast bars in the 3rd screen above.
<Border Background="#20000000">
<fxglitz:Effects.HoverEffect>
<fxglitz:ColorFillEffect FillColor="#80000000" Duration="00:00:0.5" Easing="QuadraticInOut" />
</fxglitz:Effects.HoverEffect>
...
</Border>
You can download the framework, and the associated samples here. Very soon I will be putting this up on my projects site for folks to track in a bit more organized way than following just the blog posts.
Glitz: Effects and Transitions
An effect is basically a behavior that can be attached to an element and triggered upon some event. Each effect encapsulates two animations - a forward animation and a reverse animation that it alternates between. Effects can be told to play in forward only mode, reverse only mode, or automatically reverse after completing their forward animation.
Effects are extensible. Some of the effects I have built into the framework include: Resize, Move, Spin, Fade, Highlight, ColorFill, Shake, and Pulsate. Effects are composable. CompositeEffect can play a set of child effects in parallel or in sequence.
Transitions derive from Effect, and can be attached to a panel that contain two child elements. The transition basically uses animations to hide the top element to reveal the bottom element. Like effects, transitions have forward and reverse behavior that allow them to revert back to the top element. So far the framework has four transitions built in: CrossFade, Blinds, Slide, and Flip.
Effects and transitions are both attached to UI elements as behaviors. The Effects class exposes various attached properties such as ClickEffect, HoverEffect, FocusEffect, LoadEffect, and TimedEffect. As the names suggest effects and transitions can be hooked up to mouse clicks, mouse hovers, keyboard focus, load events and timer tick events.
Effects and transitions build on a procedural animation framework that makes it very simple to write new and interesting behaviors and computed animations. The animation framework itself can be used independently of the effects layer. It provides the ability to implement unbounded (by time) animations, as well as duration-bound animations. The duration bound animations can easily tap into a set of easing functions commonly thought of as tweening options, that allow animations to accelerate on start (ease in), decelerate on end (ease out), as well as easily provide the perception of elastic rubber bands or bounce behaviors.
Effect and Transition Gallery
If you download the code, you'll see a number of effect and transition classes in the Silverlight.FX.UserInterface.Glitz namespace. Most of those can be seen in action in the screen shot below (again click to run).

For example, here is the complete XAML for the Highlight effect:
<Grid>
<Grid.RowDefinitions>...</Grid.RowDefinitions>
<fxglitz:Effects.ClickEffect>
<fxglitz:HighlightEffect TargetName="highlightImage" HighlightColor="Yellow" Duration="00:00:01" />
</fxglitz:Effects.ClickEffect>
<Border x:Name="highlightImage">
<Image Source="/Silverlight.png" />
</Border>
<TextBlock Grid.Row="1">Highlight</TextBlock>
</Grid>
For a transition example, here is the complete XAML for the Flip effect:
<Grid>
<Grid.RowDefinitions>...</Grid.RowDefinitions>
<fxglitz:Effects.ClickEffect>
<fxglitz:FlipTransition TargetName="flipContainer" Duration="00:00:1" Easing="QuadraticInOut" />
</fxglitz:Effects.ClickEffect>
<Grid x:Name="flipContainer">
<Image Source="/MS.net.png" />
<Image Source="/Silverlight.png" />
</Grid>
<TextBlock Style="{StaticResource staticText}" Grid.Row="1">Flip</TextBlock>
</Grid>
What other interesting effects and transitions would you love to see? Or better yet, try building one and using the underlying procedural animation framework, and share the experience.
Adding Effects and Transitions to Controls?
One thing I haven't shown in the samples, but I've just begun prototyping is higher-level controls that have a property of type Effect. To share one scenario, imagine a List control that has ShowEffect and HideEffect properties - it plays the effect assigned to ShowEffect on any item that is added to the list, and plays the effect assigned to HideEffect on any item that is removed from the list. This will allow creating a web 2.0 style list user interface (ala JQuery/scriptaculous) completely declaratively using pre-packaged animation effects.