by
kirupa | 17 October 2009
In the
previous page,
you added some code and got your circle moving when
you previewed it. Now comes the really fun part -
learning why the various components work the way
they do.
Before
diving into the code, I think it is helpful to look
at the bigger picture and how everything works. An
animation is nothing more than something
changing over a period of time. That
something could be a whole host of
things, but for this example (and many others),
something refers to properties.
Over a period of time,
some property changes, and this property change is
what we notice. In our example, what properties are
changing? Looking at what our animation is doing. It
is moving the circle in a circular fashion, and
the properties that are changing seem to be
horizontal position and the vertical position of the
circle:
There are basically
two things we are doing in our code:
-
Setting the
properties representing the horizontal and
vertical position.
-
Changing the
properties at a given time using some sort of a
timer-like mechanism.
At each tick of the
clock, we change our properties gradually to give
you the illustion of smooth movement. That is, of
course, easier said than done. The preceding
sentence is what I converted into all the C# code
that you copied and pasted earlier. Don't let the
volume of the code scare you though, for in the next
section, we'll try to make sense of it all.
Ok, now that you have
a conceptual understanding of what programmatic
animations do - change properties over a period of
time, let's see how all of that looks translated
into code. I'm going to be starting at the top of
BlueCircle.xaml.cs
and move down.
The first handful of
lines are just declaring variables:
- private
static
Random
randomMain
=
new
Random();
-
- private
double
angle;
- private
double
speed;
-
- private
double
xPos;
- private
double
yPos;
The only thing that I
will call out is that our randomMain variable is
declared using the static
modifier. The reason is that I want to persist only
a single Random
object throughout this application's life. This has
to do with how random numbers are initialized in
.NET, but I will delve further into random numbers in a
different article sometime in the future.
-
public
BlueCircle()
-
{
-
// Required to initialize variables
-
InitializeComponent();
-
- this.Loaded
+=
new
RoutedEventHandler(CircleLoaded);
-
}
Next up is our BlueCircle constructor. If you are
not familiar with what a constructor actually is,
I'm going to refer you to my earlier
tutorial on Classes. In a nutshell, it is
basically the gateway to your code that is provided
for you by default.
I added one line to our constructor, and that
line is the non-grayed out one you see above. I am
associating our UserControl's
Loaded event with an
event handler called
CircleLoaded. Translated into English, when my
circle usercontrol loads, I want to the CircleLoaded
function to be called.
Speaking of CircleLoaded...
- void
CircleLoaded(object
sender,
RoutedEventArgs
e)
- {
- xPos
=
Canvas.GetLeft(this);
- yPos
=
Canvas.GetTop(this);
-
- speed
= .01
+
randomMain.NextDouble();
-
- if
(System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)
==
false)
- {
-
CompositionTarget.Rendering
+=
new
EventHandler(AnimateCircle);
- }
- }
...let's look at it next. The CircleLoaded
method, like I mentioned earlier, gets called when
the Loaded event is fired. The first two variables
initialize our horizontal and vertical positions
that we declared earlier as
xPos and yPos:
- xPos
=
Canvas.GetLeft(this);
- yPos
=
Canvas.GetTop(this);
I am getting the x and y positions of this user
control by using the
Canvas.GetLeft and
Canvas.GetTop properties. This is the closest
thing to a clean syntax you get in C# for getting an
element's position
In the next line, I set the speed of our
movement:
- speed
= .01
+
randomMain.NextDouble();
Notice that our static
randomMain variable is used to set a really small
random number. As you will see shortly, there is a
reason why the number is as small as it is.
The next statement
block is interesting:
- if
(System.ComponentModel.DesignerProperties.GetIsInDesignMode(this)
==
false)
- {
-
CompositionTarget.Rendering
+=
new
EventHandler(AnimateCircle);
- }
This
if statement has no
bearing on what you see when you test your
appllication. This is to ensure that the code I am
going to talk about next does not run inside
Expression Blend. I will describe the cool feature
about this at a later time.
Ok, we have one more
line left to describe, and I am going to describe in
the
next page - that's how important that line is.
Onwards to the
next page!
|