Up to Windows 8, we were used to see software that was static from the UI point of view. Most of the times the program showed forms and dialogs without any license to the eye pleasure, without using any form of animation to introduce functions and requests. This was mostly because of the low power of previous systems but also because, deal with animations was an hard and costly task that tipically remained an unsatisfied desire.
WPF and Silverlight introduced a wide toolset for animations, unfortunately it was still too much complex to be handled in a right way. Animations are something that need to be carefully planned, designed and driven, so, also is much more advanced and easy than the past, people simply omitted to use them widely.
With Windows 8 and Store Applications, the animations not only became one of the pillars of a beautiful application, making it much more appealing for the market, but it is now also a fact of usability that communicate fluidness and effectiveness to the user while he is using the interface. For this being easy for developers, the framework introduced a set of animations and transitions that are predefined and ready for a whole set of common interface patterns
XAML and HTML: two different ways
When dealing with animations and transitions, HTML and XAML work in a very different way. There is not any reason to think that one is better than the other, because the way they works depends from their intrinsic nature.
With XAML it is easy to create animations like attachable behaviors, extending the markup with specific tags and properties. And it is the way they choose to go. Each visual element contains some properties made to apply some kind of transition and for animations they exists a predefined set to be used.
HTML instead is not easily extensible like XAML so, to create a toolset they decided to add a specific namespace to WinJS. It is WinJS.UI.Animation. Inside this namespace one find the required methods that are able to create the animation, passing the needed actors as an argument. Let see an example:
1: <StackPanel.ChildrenTransitions>
2: <TransitionCollection>
3: <EntranceThemeTransition />
4: </TransitionCollection>
5: </StackPanel.ChildrenTransitions>
The previous snippet shows a transition that apply to the children of a stack panel. When you add or remove a children from the panel, it is subject to an animation from right to left to emphasize the entrance. This same animation can be also applied to the ItemsControl via ItemContainerTransition property:
1: <ItemsControl.ItemContainerTransitions>
2: <TransitionCollection>
3: <EntranceThemeTransition />
4: </TransitionCollection>
5: </ItemsControl.ItemContainerTransitions>
So, when you add an item to the Items collection it has automatically applied the same transition. This is really useful for every control that derives from ItemsControl, like GridViews and ListViews.
1: private void Button_Click(object sender, RoutedEventArgs e)
2: {
3: this.items.Items.Insert(0,
4: new Ellipse
5: {
6: Width = 50.0,
7: Height = 50.0,
8: Fill = new SolidColorBrush(Colors.Red),
9: Margin = new Thickness(5.0)
10: });
11: }
To achieve a similar (but not equal) effect in HTML you have to prepare your animation from the Javascript code. So you have first to locate your container, the eventually affected elements, then you create the new element and setup the animation just before adding the element to the container. Finally you need to manually start the transition calling the execute() method. Here is an example:
1: function AddElementWithTransition()
2: {
3: // locate the container
4: var list = element.querySelector("#theContainer");
5:
6: // find elements that is affected by the animation (they may move when an element is added)
7: var affectedItems = document.querySelectorAll(".listItem");
8:
9: // create the new item to add
10: var newItem = document.createElement("div");
11: newItem.className = "listItem";
12: newItem.style.background = randomColor();
13:
14: // setup the animation
15: var addToList = WinJS.UI.Animation.createAddToListAnimation(newItem, affectedItems);
16:
17: // insert the new item into the collection
18: list.insertBefore(newItem, list.firstChild);
19:
20: // execute the transition
21: addToList.execute();
22: }
So, playing with transitions with HTML is not so simple as it is with XAML but as I've already said, this depends on the way the languages works. Up to here we have seen only animations that applies to collections. There are definitely other animations that apply to single object. In the following example you can see how to apply a fade in/out to an HTML element.
1: var item = document.querySelectorAll("#item");
2:
3: // fade in
4: WinJS.UI.Animation.fadeIn(item);
5:
6: // fade out
7: WinJS.UI.Animation.fadeOut(item);
This is also available in XAML with the specific FadeInThemeAnimation and FadeOutThemeAnimation. These are real animations and not transitions so you have to add them to a storyboard and the invoke the Begin method as you would do with a DoubleAnimation. They are actually a shortcut to have a predefined fade to attach to an element:
1: <Page.Resources>
2: <Storyboard x:Name="FadeIn">
3: <FadeInThemeAnimation TargetName="ellipse" />
4: </Storyboard>
5: <Storyboard x:Name="FadeOut">
6: <FadeOutThemeAnimation TargetName="ellipse" />
7: </Storyboard>
8: </Page.Resources>
9:
10: <StackPanel x:Name="root" Background="{StaticResource ApplicationPageBackgroundThemeBrush}">
11: <Ellipse x:Name="ellipse" Width="100" Height="100" Fill="Orange"
12: PointerEntered="button_PointerEntered" PointerExited="button_PointerExited" />
13: </StackPanel>
Then in C# you have to handle the events and call the right storyboard begin method. Given that they are animation, you can manipulate their properties to change duration, speed, begin time and so on.
1: protected override void OnNavigatedTo(NavigationEventArgs e)
2: {
3: FadeOut.Begin();
4: }
5:
6: private void button_PointerEntered(object sender, PointerRoutedEventArgs e)
7: {
8: FadeIn.Begin();
9: }
10:
11: private void button_PointerExited(object sender, PointerRoutedEventArgs e)
12: {
13: FadeOut.Begin();
14: }
You are also enabled to use these animation with VisualStateManager, that means apply them also to ControlTemplates with all the benefit you can figure out. There are a number of animations available, and you can simply exchange on with the other to change the effect. Here is an example that emulates the pointer up/down effect as it works with clickable elements:
1: <Page.Resources>
2: <Storyboard x:Name="FadeIn">
3: <PointerDownThemeAnimation TargetName="ellipse" />
4: </Storyboard>
5: <Storyboard x:Name="FadeOut">
6: <PointerUpThemeAnimation TargetName="ellipse" />
7: </Storyboard>
8: </Page.Resources>
As for fading, this is also available in HTML with the corresponding pointerUp and pointerDown methods:
1: var item = document.querySelectorAll("#item");
2:
3: // fade in
4: WinJS.UI.Animation.pointerDown(item);
5:
6: // fade out
7: WinJS.UI.Animation.pointerUp(item);
You have to be aware that Javascript has an important advantage here. Infact the "item" can be expressed in different ways, and not only as a single object. If you use the querySelectorAll method, you can pass a number of items to the method and have all the items to be affected by the animation, In XAML you have to create a new instance of animation for each element and then include all in the same Storyboard. Not so clean.
Handling the lifetime.
Lifetime with animation is important, specifically when you need to do something at the end of an animation. As an example you can concatenate an animation to another or setup the backward animation for an element. For this need in XAML you only have the Complete event that is raised when the animation goes to the end. This event may be handled easily in C#:
1: <Page.Resources>
2: <Storyboard x:Name="PointerDown">
3: <PointerDownThemeAnimation TargetName="ellipse" />
4: </Storyboard>
5: <Storyboard x:Name="FadeIn" Completed="FadeInThemeAnimation_Completed">
6: <FadeInThemeAnimation TargetName="ellipse" />
7: </Storyboard>
8: <Storyboard x:Name="PointerUp" Completed="PointerUpThemeAnimation_Completed">
9: <PointerUpThemeAnimation TargetName="ellipse" />
10: </Storyboard>
11: <Storyboard x:Name="FadeOut">
12: <FadeOutThemeAnimation TargetName="ellipse" />
13: </Storyboard>
14: </Page.Resources>
After setting up these animation you can drive them in code:
1: private void button_PointerEntered(object sender, PointerRoutedEventArgs e) { FadeIn.Begin(); }
2: private void button_PointerExited(object sender, PointerRoutedEventArgs e) { PointerUp.Begin(); }
3: private void PointerUpThemeAnimation_Completed(object sender, object e) { FadeOut.Begin(); }
4: private void FadeInThemeAnimation_Completed(object sender, object e) { PointerDown.Begin(); }
This creates a double effect that merges the fading with the pointer animations. To achieve a similar result you can use promises in Javascript. Each animation you setup is exposed as a promise so you can use the .then() and .done() methods to concatenate and drive other animations.
1: function onPointerDown(evt) {
2: WinJS.UI.Animation.pointerUp(evt.srcElement).then(
3: function ()
4: {
5: WinJS.UI.Animation.fadeOut(evt.srcElement);
6: });
7: }
8:
9: function onPointerUp(evt) {
10: WinJS.UI.Animation.fadeIn(evt.srcElement).then(
11: function ()
12: {
13: WinJS.UI.Animation.pointerDown(evt.srcElement);
14: });
At the very end, using promises is much more easy than events, just because you only need to figure out the sequence and write it in code. Using events make your code hard to be read.
Taking advantage of animation and transitions
As I said at the very beginning of the article, there is a huge benefit from using animations and transitions. They are specifically targeted to give a fedback to the user that is important expecially when dealing with touch interfaces. In these cases infact, rollover effects that are common when the mouse is the main pointing device, becomes unuseful with fingers. Additionally, an animated interface gives a impression of fluidity that make the user aware of what is happening.
It is really important to use animations, almost as important as it is not to abuse of them. You have to have always in mind that:
-
use always the same animation for the same action. Having different animations applied for the same actions is for source of confusion for the final user.
-
be always aware of the status of your animation. Please do not forget to reset them to the initial status when required because differently the can create ugly effects on you interface
-
animations as heavy. So please avoid to animate a numebr of items together (as in a gridview) because the user will be forced to wait a long time for the animation to end.
These suggestion applies both to HTML and XAML. No matter the toolset you use, what really means it the result you achieve.