by
kirupa | 14 May 2008
In the
previous page,
I described the problem and why it is necessary to
modify this animation using code. In this page,
we'll look at the problem in greater detail.
To help you out,
I've created a sample project that represents our
problem:
Download the above
file, extract it to your hard drive, and open
Window1.xaml in
Expression Blend 2. Hit F5 to run your
application. What you will see is the application I
described in the previous page - animation and all.
What I am going to do
in this page is describe the XAML that defines the
animation where the circle oscillates from one edge
of the window to the other. The reason is that, in
order to manipulate this animation using C#, knowing
the basic structure of your animation in XAML is
quite handy.
In Blend 2, hit the
XAML tab and scroll to the top of your code where you see
the Window.Resources node. It's child is the
animation that I have pasted below for your
reference:
- <Storyboard
x:Key="Oscillate">
- <DoubleAnimationUsingKeyFrames
-
BeginTime="00:00:00"
-
RepeatBehavior="Forever"
-
Storyboard.TargetName="ellipse"
-
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[3].(TranslateTransform.X)">
-
- <SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:00"
- Value="0"/>
- <SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:01"
- Value="-130"/>
- <SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:02"
- Value="0"/>
- <SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:03"
- Value="140"/>
- <SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:04"
- Value="0"/>
-
- </DoubleAnimationUsingKeyFrames>
- </Storyboard>
Animations in WPF and Silverlight are defined by
three things - Storyboards, Animations, and
Keyframes. Let's look at each one in greater detail
by using our above XAML as reference.
A storyboard primarily acts a
container for your animations. While it can do more
such as specify which elements and properties to
target, our storyboard only contains an
x:Key reference
that will prove useful when calling this storyboard
via code:
- <Storyboard
x:Key="Oscillate">
-
<DoubleAnimationUsingKeyFrames
-
BeginTime="00:00:00"
-
RepeatBehavior="Forever"
-
Storyboard.TargetName="ellipse"
-
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[3].(TranslateTransform.X)">
-
-
<SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:00"
-
Value="0"/>
-
<SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:01"
-
Value="-130"/>
-
<SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:02"
-
Value="0"/>
-
<SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:03"
-
Value="140"/>
-
<SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:04"
-
Value="0"/>
-
-
</DoubleAnimationUsingKeyFrames>
- </Storyboard>
The main thing to note
in the context of this example is that our
storyboard's x:Key value is Oscillate.
Inside your storyboard, you
will find animations. There are numerous (I believe
22) animation base types that you can use, and they
are all designed for whatever type of property you
are modifying:
- <Storyboard
x:Key="Oscillate">
- <DoubleAnimationUsingKeyFrames
-
BeginTime="00:00:00"
-
RepeatBehavior="Forever"
-
Storyboard.TargetName="ellipse"
-
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[3].(TranslateTransform.X)">
-
-
<SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:00"
-
Value="0"/>
-
<SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:01"
-
Value="-130"/>
-
<SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:02"
-
Value="0"/>
-
<SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:03"
-
Value="140"/>
-
<SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:04"
-
Value="0"/>
-
- </DoubleAnimationUsingKeyFrames>
- </Storyboard>
Our animation is of
type DoubleAnimationUsingKeyframes because, we are
using keyframes as you will see later, but more
importantly, because the property we are modifying -
TranslateTransform.X
- is of type Double.
Notice that we set
some basic properties such as BeginTime and
RepeatBehavior which specify when your animation
begins and what it will do when it reaches the end.
In our case, the animation begins at time 0, and
when it reaches the end, it loops forever.
What is interesting to
note is the value for your
TargetProperty.
Notice that it seems pretty big, but if you look
through it, the property that you are targeting is
the TranslateTransform.X property of your
RenderTransform on
the ellipse element. In Blend, you can find that
property by using the Properties Inspector and
navigating to the Transform category:
[
the property that your animation is targeting ]
I'm showing this to
let you know that your animation has its sights on
the X value of your RenderTransform. You will see
why that is important in the next section when I
describe keyframes.
Animations often contain
keyframes. Keyframes are like a stake in the ground
where a property promises to be at a particular
value at the time the keyframe is in. In our
example, we have five keyframes of type
SplineDoubleKeyFrame:
- <Storyboard
x:Key="Oscillate">
-
<DoubleAnimationUsingKeyFrames
-
BeginTime="00:00:00"
-
RepeatBehavior="Forever"
-
Storyboard.TargetName="ellipse"
-
Storyboard.TargetProperty="(UIElement.RenderTransform).
(TransformGroup.Children)[3].(TranslateTransform.X)">
-
- <SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:00"
- Value="0"/>
- <SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:01"
- Value="-130"/>
- <SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:02"
- Value="0"/>
- <SplineDoubleKeyFrame
-
KeySpline="0,1,1,1"
-
KeyTime="00:00:03"
- Value="140"/>
- <SplineDoubleKeyFrame
-
KeySpline="1,0,1,1"
-
KeyTime="00:00:04"
- Value="0"/>
-
-
</DoubleAnimationUsingKeyFrames>
- </Storyboard>
You can visualize
these keyframes by simply opening the Oscillate
storyboard in Blend:
[
your five keyframes displayed at times 0, 1, 2, 4,
and 5 second marks ]
Notice that there are
five keyframes, and if you select the keyframe, you
will see your Properties Inspector update to display
the keyframe and the type it is, and more
importantly, its value:
[
selecting a keyframe will display it's type plus a
field for its value ]
Anyway, but now I am
digressing. If you look at the XAML, the KeyTime is
specified, but so is the
Value. This Value is channeled to the
TargetProperty your animation is targeting. For
example, at the 3 second mark, your KeyFrame's Value
is 140. That means that our ellipse's
TranslateTransform.X value is going to be 140 as
well.
In case I didn't
mention it earlier, the animation system in WPF and
Silverlight is really designed to take a property
and change it over a period of time. In our case, we
are changing the horizontal position of our circle
(ellipse element) via the TranslateTransform.X
property as defined by our animation, and the actual
value of that property at a given time is specified
by our keyframes.
All right, now you
have a good idea of what our XAML is actually doing
by analyzing our animation. As you will see in the
next page, this knowledge will come in quite
handy.
Onwards to the
next page!
|