I have been working on a small media player application on WPF these days. And since I’m going full Metro on it , I needed some good animations and transitions.
The main idea is to have a one screen for everything and then just slide in/out whole content with the help of a little menu at the top right. This menu should have like 2-3 horizontal layers , one layer for stuff like settings , help , about etc , then another layer for main menu items , and probably a 3rd one for sub menus or player screen etc.
So whenever you click on a menu item ; the main view behind the menu ( whole application surface including that big blue “Management” title ) will slide left/right or top/bottom according to the layer and position of that item. Sounds good?
Being way too lazy to implement it myself , I started searching for a nice transition implementation and came across FluidKit. Althought it’s pretty old and seems abandoned , I decided to give it a shot. So I started playing with it and it was all going fine until I this little bug ; althought LeftToRight and RightToLeft transitions are working properly , there seems to be a problem with BottomToTop and TopToBottom transitions as they don’t work at all. Even when I set direction to BottomToTop by hand , it just ignores the direction and slides LeftToRight!
Only after wasting a few hours , I remembered it’s an open source project and decided to take a look at the code and found this little method , in SlideTransition class , which supposed to , well Prepare Storyboard ;
public override Storyboard PrepareStoryboard() { Storyboard animator = (TransitionResources["SlideAnim"] as Storyboard).Clone(); DoubleAnimation prevAnim = animator.Children[0] as DoubleAnimation; DoubleAnimation nextAnim = animator.Children[1] as DoubleAnimation; Storyboard.SetTargetName(prevAnim, "PrevElement"); Storyboard.SetTargetName(nextAnim, "NextElement"); prevAnim.Duration = this.Duration; nextAnim.Duration = this.Duration; // Left <-> Right transition if (Direction == Direction.RightToLeft) { prevAnim.From = 0; prevAnim.To = -1 * Owner.ActualWidth; nextAnim.From = Owner.ActualWidth; nextAnim.To = 0; } else { prevAnim.From = 0; prevAnim.To = Owner.ActualWidth; nextAnim.From = -1 * Owner.ActualWidth; nextAnim.To = 0; } return animator; }
See the problem? They just totally ignored vertical animations!
Turns out that Direction Enum is used for all transitions supported by FluidKit and vertical transitions are only used in stuff like CubeTransition. So although you get intellisense for BottomToTop and TopToBottom and even set Direction to those , FluidKit doesn’t even care , doesn’t even give an exception and just plays the default LeftToRight animation!
Now that we know what the problem is , it’s pretty easy to fix it. Well just add Top&Bottom support to PrepareStoryboard method and then add a new StoryBoard for vertical animations.
First , the PrepareStoryboard Method ;
public override Storyboard PrepareStoryboard() { Storyboard animator = null; if (Direction == Direction.RightToLeft || Direction == Direction.LeftToRight) animator = (TransitionResources["SlideAnimX"] as Storyboard).Clone(); else animator = (TransitionResources["SlideAnimY"] as Storyboard).Clone(); DoubleAnimation prevAnim = animator.Children[0] as DoubleAnimation; DoubleAnimation nextAnim = animator.Children[1] as DoubleAnimation; Storyboard.SetTargetName(prevAnim, "PrevElement"); Storyboard.SetTargetName(nextAnim, "NextElement"); prevAnim.Duration = this.Duration; nextAnim.Duration = this.Duration; // Left <-> Right transition if (Direction == Direction.RightToLeft) { prevAnim.From = 0; prevAnim.To = -1 * Owner.ActualWidth; nextAnim.From = Owner.ActualWidth; nextAnim.To = 0; } else if (Direction == Direction.LeftToRight) { prevAnim.From = 0; prevAnim.To = Owner.ActualWidth; nextAnim.From = -1 * Owner.ActualWidth; nextAnim.To = 0; } else if (Direction == Direction.BottomToTop) { prevAnim.From = 0; prevAnim.To = -1 * Owner.ActualHeight; nextAnim.From = Owner.ActualHeight; nextAnim.To = 0; } else if (Direction == Direction.TopToBottom) { prevAnim.From = 0; prevAnim.To = Owner.ActualHeight; nextAnim.From = -1 * Owner.ActualHeight; nextAnim.To = 0; } return animator; }
So instead of ignoring vertical animations , we handle them properly and set the From&Top properties of animation according to the direction ( notice we’re using ActualyHeight instead of Width for vertical animations ).
Oh and it turns out FluidKit uses storyboards from a xaml instead of creating them in code. I played along and didn’t changed that ;
TransitionStoryboards.xaml ;
<Storyboard x:Key="SlideAnim"> <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)" DecelerationRatio="1.0"/> <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.X)" DecelerationRatio="1.0"/> </Storyboard> <Storyboard x:Key="SlideAnimY"> <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" DecelerationRatio="1.0"/> <DoubleAnimation Duration="0:0:0.5" Storyboard.TargetProperty="RenderTransform.(TranslateTransform.Y)" DecelerationRatio="1.0"/> </Storyboard>
I decided to post this as it seems there are still a few people using FluidKit out there. Hope it helps , you can find an example solution file below.
Visual Studio 2010 Solution