This walkthrough steps you through the creation of a simple clock using Microsoft Silverlight. The following illustration shows the clock that you will create.
.png)
Run this sample.
Download this sample.
The vector graphics that make up the appearance of the clock are created by using the Extensible Application Markup Language (XAML). XAML is similar to HTML except that it is more powerful and extensible. XAML can be typed in manually by using Microsoft Visual Studio or Microsoft Notepad, or you can use a visual design tool such as Microsoft Expression Blend. Expression Blend works by creating underlying XAML code, so both methods create the same graphics for the clock.
To complete the first part of this walkthrough, select one of the options below:
In the next two steps, you add animations and logic to make the clock work. In Microsoft Silverlight, you can use a browser-interpreted language such as JavaScript or managed code such as C# or VB .NET. This walkthrough will show you how to add animations and logic using C# or VB. To learn more about using JavaScript to create Silverlight-based applications, see JavaScript API for Silverlight or JavaScript API for Silverlight Reference.
You need the following components to complete this walkthrough (available from the Silverlight download site):
Creating Clock Graphics Using Expression Blend
Microsoft Expression Blend will speed up the creation of your Silverlight-based application, especially when you're designing graphics and layout.
In this section of the walkthrough, you will create the graphics for the clock by using Expression Blend.
The clock consists of the graphical elements shown in the following illustration.
.png)
These graphics are created with simple elements arranged on a canvas. All the circular graphics, including the clock face, outer rim, bevel, and shadow, are created with Ellipse elements, and the clock hands are created with Rectangle elements.
To create a new project in Expression Blend
Start Expression Blend. (Click Start, point to All Programs, point to Microsoft Expression, and then click Microsoft Expression Blend 2.5.)
On the File menu, click New Project. The following dialog box is displayed.
.png)
In the Name box, type SilverlightClock.
In the Language list, click to choose C# or Visual Basic as your programming language.
Select Silverlight 3 Application and click OK.
At this point you have an empty project. If you press F5 to run the application, you will only see a blank Web page.
The graphics of the clock consists of layers of overlapping shapes, which create the overall appearance of a clock. To create the clock, you will build the clock up one layer at a time, starting with the lowest layer, which is the shadow of the clock.
The following illustration shows what the shadow of the clock will look like when the sample is complete.
.png)
To create the shadow of the clock
Select the Ellipse tool.
.png)
Drag and drop the ellipse on the canvas to create a circle approximately 330 pixels wide and high.
.png)
Change the circle properties. Click the Properties tab, give the circle a fill of black, and set the opacity to 30%.
.png)
The circle now has a fill of semi-transparent black, which will provide the shadow effect.
Change the name of the ellipse to shadowEllipse.
.png)
The illustration below shows the outer rim of the clock when the sample is complete.
.png)
To create the outer rim of the clock
Draw the outer rim circle. The circle for the outer rim is the same size as the shadow circle. Therefore, you can create it by simply making a copy of the shadow circle. To do this, select the shadow circle, press CTRL+C to copy it, and CTRL+V to paste a copy. Rename this ellipse outerRimEllipse.
Now you will fill outerRimEllipse with a simple gradient. Creating a gradient in Expression Blend consists of several steps.
Create a simple gradient.
.png)
Move the right gradient stop to concentrate the gradient on the left side. Note: you may have to change the direction of the gradient so that it runs from left to right (see step 5 below).
.png)
Move outerRimEllipse slightly to the upper left to see the shadow. You will notice a sliver of shadowEllipse visible in the lower right, which creates a shadow effect.
.png)
Change the direction of the linear gradient so that it is going from the upper left to the lower right (instead of going from left to right over the circle).
.png)
The gradient direction is shown in the following illustration.
.png)
Now you will create the bevel of the clock. The circle you use to make the bevel will be similar to outerRimEllipse, only a little smaller. The following illustration shows the bevel when the sample is complete.
.png)
To create the bevel of the clock
Create a copy of outerRimEllipse. To do this, select outerRimEllipse, press CTRL+C to copy it, and press CTRL+V to paste it. Name the new ellipse bevelEllipse.
Select bevelEllipse and resize it to approximately 290 pixels high and wide to make it slightly smaller than outerRimEllipse.
Position bevelEllipse so that it is in the center of outerRimEllipse.
.png)
Now you will fill BevelEllipse with a linear gradient.
Create the basic gradient. Because bevelEllipse is a copy of outerRimEllipse, it will already have a gradient applied to it.
Change the color of the left gradient stop to #FF2F2F32, and change the color of the right gradient stop to #FFE4E5F4.
Slide the right gradient stop back to the right-hand end of the gradient.
.png)
This gradient runs in the same direction as the gradient applied to outerRimEllipse. However, the bevelEllipse gradient goes from dark in the upper-left to light in the lower-right, which is the opposite of the gradient applied to outerRimEllipse. The illustration below shows the direction of the gradient.
.png)
Next, you will create the face of the clock. The circle you use to make the face will be similar to bevelEllipse, only a little smaller. The following illustration shows the clock face when the sample is complete.
.png)
To create the face of the clock
Create a copy of bevelEllipse. To do this, select bevelEllipse, press CTRL+C to copy it, and press CTRL+V to paste it. Name the new ellipse faceEllipse.
Select faceEllipse and resize it to approximately 270 pixels high and wide to make it slightly smaller than bevelEllipse.
Position faceEllipse so that it is in the center of outerRimEllipse.
.png)
Change the fill of faceEllipse to black.
.png)
Notice that the addition of this circle makes the bevel visible.
.png)
Next, you will create the center circle of the clock. The following illustration shows the center circle when the sample is complete.
Center circle of the clock
.png)
To create the center circle of the clock
Select the Ellipse tool, and drag the new ellipse on top of the clock face.
Change the name of the new ellipse to centerEllipse.
Set the height and width of centerEllipse to 30.
Set the stroke thickness to 8, and set the stroke to green.
.png)
Position the center circle in the middle of the clock face. To find the center of faceEllipse, select faceEllipse and look for its center point. Then select centerCircle and drag and drop or use the arrow keys to move the centerCircle over the center point of faceEllipse.
.png)
Next, you will create the hands of the clock.
To create the hands of the clock
Select the Rectangle tool.
.png)
Create the second hand. The second hand is a thin, red line. Drag a line pointing to the 12 o’clock position. Call the line secondHand and give it a stroke thickness of 5, a height of 80, and a fill color of red.
.png)
Move the transform center point to the middle of the clock face: The transform center point is the point relative to which transforms are applied. Later, you will animate the clock hands around the center of the clock. Therefore, you need to move the center point of the line to the middle of the clock face. To access the center point of the line, drag the width of the rectangle until you see a white dot in the middle of the rectangle. Then drag the white dot to the middle of the center circle.
.png)
Create the minute hand by following steps 2 and 3 for the second hand.
Make the line approximately the same length as secondHand and position it in the 12 o’clock position, on top of secondHand. Name the line minuteHand.
Give minuteHand a stroke thickness of 8 (slightly thicker than secondHand) and a stroke color of green.
Place the center point of minuteHand in the center of the clock face, following the instructions in step 3.
Create the hour hand by following the preceding steps for the second hand and the minute hand.
Make the line about 2/3 as long as the other clock hands and position it in the 12 o’clock position, on top of the other clock hands. Name the line hourHand.
Give hourHand a strokethickness of 10 (thicker than the other hands) and a stroke color of green.
Place the center point of hourHand in the center of the clock face.
Later, you will add animations that rotate the hands around the clock. This will be done by animating the Angle property of the RotateTransform element that is applied to the clock hand. Because the animation will have to target the correct RotateTransform, you will have to name the RotateTransform elements applied to each of the clock hands. To do this, open the XAML editing view in Expression Blend.
.png)
The clock hands are created with Rectangle elements. Find the clock hand rectangles in the XAML. If there is already a RotateTransform applied to the path, give it a name using the syntax in the following code, and leave the rest of the code alone for now. Name the elements secondHandTransform, minuteHandTransform, and hourHandTransform, respectively. If a RotateTransform does not already exist, add one, as shown in the following code.
<!-- Second Hand -->
<Rectangle x:Name="secondHand" ...>
<Rectangle.RenderTransform>
<RotateTransform x:Name="secondHandTransform"/>
</Rectangle.RenderTransform>
</Rectangle>
At this point, you have created the graphics for the clock. Skip the section below. Next, you will add the animations and logic required to make the clock work.
Creating Clock Graphics Using XAML
Instead of using Microsoft Expression Blend, you can create the graphics for the clock directly in markup language, by using XAML. This section of the walkthrough shows how.
Working directly in code to create Silverlight-based applications is easiest when using Visual Studio 2008.
To create a new Silverlight project in Visual Studio 2008
If you have not already done so, install Visual Studio 2008.
If you have not already done so, install Microsoft Silverlight Tools for Visual Studio 2008. This provides Silverlight templates that plug into Visual Studio.
Open Visual Studio. On the File menu, click New, and then click Project.
To use C#, click Visual C# and Silverlight on the left-hand pane and Silverlight Project under Templates. To use Visual Basic, click Visual Basic and Silverlight on the left-hand pane and Silverlight Application under Templates. Name the project SilverlightClock.
.png)
After you click ok, you will see a dialog box. Check the radio button "Dynamically generate an HTML test page to host Silverlight within this project" and press ok. This will create a blank Silverlight project. Run the project in debugging mode by pressing F5. As expected, a blank Web page opens up. You can end debugging mode by either clicking Debug/Stop Debugging from the menu or by closing the browser window.
Let’s start by previewing how to create the graphics for the clock. The clock consists of the graphical elements shown in the following illustration.
.png)
These graphics are created with simple elements arranged on a canvas. All of the circular graphics such as the clock face, outer rim, bevel, and shadow are created with Ellipse elements, and the clock hands are created with simple Rectangle elements. The graphics are composed of layers of overlapping shapes, which create the overall appearance of a clock. To create the clock, you will build the clock up one layer at a time, starting with the lowest layer (the shadow of the clock).
The following illustration shows what the shadow of the clock will look like when the sample is complete.
.png)
To create the shadow of the clock
Copy the following code to your XAML page.
<UserControl x:Class="SilverlightClock.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<!-- Shadow Ellipse -->
<Ellipse Margin="165,67,145,83" Fill="#FF000000" Width="330"
Height="330" Opacity="0.3"/>
</Grid>
</UserControl>
The following illustration shows the results.
.png)
Notice that the fill is set to black and the opacity is set to 0.3 (30%). This makes the fill of the circle semi-transparent, like a shadow. The width and height as well as the margin are arbitrary. These properties simply specify the size and position of the circle within the Grid.
Note: |
|---|
Most XAML code in Silverlight-based applications is not affected by the procedural language you use (for example, C#, Visual Basic, or JavaScript). |
Next, you will add the outer rim of the clock. The illustration below shows the outer rim when the sample is complete.
.png)
To add the outer rim
Copy the following code to the XAML page after the ellipse used to create the shadow:
<Grid x:Name="LayoutRoot">
<!-- Shadow Ellipse -->
<Ellipse Margin="165,67,145,83" Fill="#FF000000" Width="330"
Height="330" Opacity="0.3"/>
<!-- Outer Rim -->
<Ellipse Height="330" Margin="156,58,154,92" Width="330"
Stroke="#FF000000">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.84,0.87" StartPoint="0.164,0.129">
<GradientStop Color="#FFE4E5F4"/>
<GradientStop Color="#FFC0C0C0" Offset="0.254"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
</Grid>
The following illustration shows the results.
.png)
As you can see from the illustration, the shadow circle is positioned slightly to the lower right, allowing only a sliver of that circle to be visible from underneath. This results in a shadow effect. Also, notice that a linear gradient is applied to the outer rim circle. This linear gradient is positioned to create the appearance of light coming from the upper left of the circle. The gradient direction is illustrated in the following illustration.
.png)
Next, you will add the bevel of the clock. The following illustration shows the bevel when the sample is complete.
.png)
To add a bevel to the clock
Copy the following code to the XAML page after the ellipse used to create the outer rim:
<!-- Bevel -->
<Ellipse Height="290" Margin="156,58,154,92" Width="290"
Stroke="#FF000000">
<Ellipse.Fill>
<LinearGradientBrush EndPoint="0.84,0.87" StartPoint="0.164,0.129">
<GradientStop Color="#FF2F2F32"/>
<GradientStop Color="#FFE4E5F4" Offset="0.987"/>
</LinearGradientBrush>
</Ellipse.Fill>
</Ellipse>
The following illustration shows the results.
.png)
This circle is slightly smaller than the circle used to create the outer rim, and it is positioned directly over the outer rim circle. In addition, this circle also has a linear gradient applied to it, but this gradient goes from dark in the upper left to light in the lower right. The following illustration shows the direction of the gradient.
.png)
Next, you will add the face of the clock. The illustration below shows the face when the sample is complete.
.png)
To add the clock face
Copy the following code to the XAML file after the last ellipse you added.
<!-- Clock Face -->
<Ellipse Height="270" Margin="176,78,174,112" Width="270"
Stroke="#FF000000" Fill="#FF000000"/>
The following illustration shows the results.
.png)
The clock face is simply a black filled circle, slightly smaller than the bevel circle, positioned directly over the other circles. Also, notice that addition of this circle makes the bevel visible.
.png)
The last step is to add the central circle and clock hands.
To add the central circle and hands
Copy the following code to the XAML file after the last code you added.
<!-- Central Clock Circle -->
<Ellipse Margin="306,208,304,0" VerticalAlignment="Top" Fill="#FF000000"
Stroke="#FF008000" StrokeThickness="8" Height="30"/>
<!-- Second Hand -->
<Rectangle Height="80" Margin="318.25,117.75,316.75,0"
VerticalAlignment="Top" Fill="#FFFF0000" Stroke="#FF000000"
Width="5" RenderTransformOrigin="0.5,1.312" >
<Rectangle.RenderTransform>
<RotateTransform x:Name="secondHandTransform"/>
</Rectangle.RenderTransform>
</Rectangle>
<!-- Minute Hand -->
<Rectangle x:Name="minuteHand" Height="80"
Margin="316.75,117.75,315.25,0" VerticalAlignment="Top"
Fill="#FF008000" Stroke="#FF008000" Width="8"
RenderTransformOrigin="0.5,1.312" >
<Rectangle.RenderTransform>
<RotateTransform x:Name="minuteHandTransform"/>
</Rectangle.RenderTransform>
</Rectangle>
<!-- Hour Hand -->
<Rectangle x:Name="hourHand" Height="59"
Margin="315.75,138.75,314.25,0" VerticalAlignment="Top"
Fill="#FF008000" Stroke="#FF008000" Width="10"
RenderTransformOrigin="0.525,1.428">
<Rectangle.RenderTransform>
<RotateTransform x:Name="hourHandTransform"/>
</Rectangle.RenderTransform>
</Rectangle>
The following illustration shows the results. The second hand, minute hand, and hour hand are overlapping in this illustration.
.png)
In the previous code, the minute hand, hour hand, and second hand share the same values for properties that determine positioning (e.g. Margin). However, the hands differ from one another in size and/or color (for example, the hour hand is thickest because it has the largest StrokeThickness value).
Notice that all of the hands have a RotateTransform applied to them. This transform enables you rotate the angle of the hand. In the next section, you will animate the angle of this transform, which will make the clock hands move to show the time. Each of the RotateTransform elements have a name (for example, x:Name="hourHandTransform"). This is done so you can associate an animation with the transform. Also, notice that all of the hands have a RenderTransformOrigin value. This property is used to specify the point on the canvas that all transforms are made relative to. Since you are going to rotate the hands around the center of the clock, the value of the RenderTransform property for all hands is given as the center of the clock face.
In the next section, you will add the animations and logic required to make the clock work
Whether you used Expression Blend to create the graphics for the clock or worked directly in XAML markup, you should now have a clock that looks like the following illustration. Note that the second hand, minute hand, and hour hand are overlapping in this illustration.
.png)
In this section, you will apply animations to the rotation transforms of the clock hands. These rotation animations will make the clock hands rotate around the center of the clock (as you would expect clock hands to do). By specifying the timing of the animations, you can make the hands rotate around the clock in sync with the current time on the computer.
To add animations
Open the XAML file.
If you used Expression Blend in the previous task, open the XAML file of the project and click the XAML tab.
.png)
If you used Visual Studio or another editing program in the previous task, open your XAML page from that program.
Add the following code after the root UserControl element to add the clock hand animations.
<UserControl.Resources>
<Storyboard x:Name="clockStoryboard">
<!-- This animation targets the hour hand transform -->
<DoubleAnimation x:Name="hourAnimation"
Storyboard.TargetName="hourHandTransform"
Storyboard.TargetProperty="Angle"
Duration="12:0:0" RepeatBehavior="Forever" To="360" />
<!-- This animation targets the minute hand transform -->
<DoubleAnimation x:Name="minuteAnimation"
Storyboard.TargetName="minuteHandTransform"
Storyboard.TargetProperty="Angle"
Duration="1:0:0" RepeatBehavior="Forever" To="360" />
<!-- This animation targets the second hand transform -->
<DoubleAnimation x:Name="secondAnimation"
Storyboard.TargetName="secondHandTransform"
Storyboard.TargetProperty="Angle"
Duration="0:1:0" RepeatBehavior="Forever" To="360" />
</Storyboard>
</UserControl.Resources>
This code defines a Storyboard that contains the animations that animate the hands of the clock. To start the Storyboard, use the Loaded event to call the Begin method on the Storyboard. To do this, first attach the Loaded event to the Grid that contains the clock graphics.
<Grid x:Name="LayoutRoot" Loaded="SetAndStartClock">
Then create an event handler that starts the Storyboard. You will have to open the code-behind file to add the following handler.
Private Sub SetAndStartClock(ByVal sender As Object, ByVal e As EventArgs)
' Start the storyboard.
clockStoryboard.Begin()
End Sub
private void SetAndStartClock(object sender, EventArgs e)
{
// Start the storyboard.
clockStoryboard.Begin();
}
All of these animations in the Storyboard target the Angle property of the respective clock hand transform. The Duration property of each animation is set depending on the desired speed of the animation. For example, for the hour hand transform, the duration of the animation is set for 12 hours, which is the time it takes the hour hand to go completely around the clock. The RepeatBehavior of all of the animations are set to "Forever". Therefore, when the animation completes (the hand goes around the clock), it starts over again and repeats indefinitely.
Run the application now. Notice that the second hand is moving around the clock. The other hands are also moving, but they are moving too slowly to be perceptible.
Although the clock hands are moving at the rate they are supposed to, the clock is not set to the current time. To set the clock, you will need to add some logic using procedural code such as C# or Visual Basic.
To make the clock work
Open the code-behind file:
If you used Expression Blend to design the graphics, open the C# file from the Project panel.
.png)
If you used Visual Studio or another editing program for your application, open your C# or VB page from that program.
Copy the following to the code-behind file to add the logic for setting the clock.
Private Sub SetAndStartClock(ByVal sender As Object, ByVal e As EventArgs)
' The current date and time.
Dim currentDate As Date = DateTime.Now
' Find the appropriate angle (in degrees) for the hour hand
' based on the current time.
Dim hourangle As Double = (((CType(currentDate.Hour, Single) / 12) * 360) + (currentDate.Minute / 2))
' The same as for the minute angle.
Dim minangle As Double = ((CType(currentDate.Minute, Single) / 60) * 360)
' The same for the second angle.
Dim secangle As Double = ((CType(currentDate.Second, Single) / 60) * 360)
' Set the beginning of the animation (From property) to the angle
' corresponging to the current time.
hourAnimation.From = hourangle
' Set the end of the animation (To property)to the angle
' corresponding to the current time PLUS 360 degrees. Thus, the
' animation will end after the clock hand moves around the clock
' once. Note: The RepeatBehavior property of the animation is set
' to "Forever" so the animation will begin again as soon as it completes.
hourAnimation.To = (hourangle + 360)
' Same as with the hour animation.
minuteAnimation.From = minangle
minuteAnimation.To = (minangle + 360)
' Same as with the hour animation.
secondAnimation.From = secangle
secondAnimation.To = (secangle + 360)
' Start the storyboard.
clockStoryboard.Begin()
End Sub
private void SetAndStartClock(object sender, EventArgs e)
{
// The current date and time.
System.DateTime currentDate = DateTime.Now;
// Find the appropriate angle (in degrees) for the hour hand
// based on the current time.
double hourangle = (((float)currentDate.Hour) / 12) * 360 + currentDate.Minute / 2;
// The same as for the minute angle.
double minangle = (((float)currentDate.Minute) / 60) * 360;
// The same for the second angle.
double secangle = (((float)currentDate.Second) / 60) * 360;
// Set the beginning of the animation (From property) to the angle
// corresponging to the current time.
hourAnimation.From = hourangle;
// Set the end of the animation (To property)to the angle
// corresponding to the current time PLUS 360 degrees. Thus, the
// animation will end after the clock hand moves around the clock
// once. Note: The RepeatBehavior property of the animation is set
// to "Forever" so the animation will begin again as soon as it completes.
hourAnimation.To = hourangle + 360;
// Same as with the hour animation.
minuteAnimation.From = minangle;
minuteAnimation.To = minangle + 360;
// Same as with the hour animation.
secondAnimation.From = secangle;
secondAnimation.To = secangle + 360;
// Start the storyboard.
clockStoryboard.Begin();
}
The clock is now finished! Press the F5 keyboard key to run the application.
Debugging Silverlight Applications in Visual Studio 2008
You can create breakpoints and step through the C# or VB code shown in this walkthrough by using Visual Studio. To create a breakpoint, click the left margin next to the line of code you want to set the breakpoint on. When you run the application, Visual Studio will pause the application at your designated breakpoint. You can then step through each line of code by pressing the F11 key or by clicking Debug/Step Into from the top menu.
In this walkthrough, you have learned how to do the following in Silverlight:
Design overlapping vector graphics that create the appearance of a real-life clock.
Use gradients to create shadowing and depth.
Use animations to add functionality to the clock.
Use code to set the clock to the correct time.
Learn how to use XAML and Microsoft Expression Blend.
Concepts