简单介绍Silverlight中的坐标系统,这能够帮助我们更加深入的理解和明白如何更好的控制Silverlight对象.
Silverlight坐标系统与几何中的坐标系统不同。几何中的坐标系统有四个象限。而Silverlight中仅仅使用了(x,-y)这个第四象限,而不同的是Y轴使用了正值表示,如下图。假设设置一个点的坐标值为(3,3)那么可以直接设置Left和Top值为3即可。坐标系中的左上角为原点(0,0),X、Y轴无限大。

一、向量
向量既有方向又有大小。比如下图表示了一个大小为3,方向为正方向的向量。

如果我们想让此向量移动到向量6,那么在原有值上加3即可。若移动为反方向那么则需要使用-9来加上原向量。因此也可以说如果要改变向量的方向可以使用向量*-1。下图分别显示了一个(5,5)的向量和不同方向大小相同的向量。

对于向量(5,5)我们分别使用此向量乘以(1,-1)、(-1,1)(-1、-1)即可得到不同方向的大小相等的向量。
知道了这些那么下面我们就来使用向量的这个特点来做一个动画.
一、使用向量控制对象在一维坐标系中运动
第一步:创建一个对象,名字叫particle.xaml .XAML代码如下:
particle.xaml 代码
<
UserControl.Resources
>
<
Storyboard
x:Name
="Move"
Duration
="00:00:00"
/>
</
UserControl.Resources
>
<
Canvas
x:Name
="LayoutRoot"
>
<
Ellipse
Width
="10"
Height
="10"
Fill
="#FFFFFF00"
Stroke
="#FF000000"
x:Name
="ball"
/>
</
Canvas
>
第二步:在代码中为particle定义一个向量,用于控制小球的速度与方向,其次订阅动画完成事件。并在完成事件中根据向量来设置particle的位置。代码如下:
Particle.xaml.cs 代码
public
partial
class
Particle : Page
{
//
方向
public
int
Direction {
get
;
set
; }
//
向量
public
double
VectorX {
get
;
set
; }
//
父容器大小
public
double
RootHeight {
get
;
set
; }
public
double
RootWidth {
get
;
set
; }
public
Particle()
{
InitializeComponent();
this
.Move.Completed
+=
new
EventHandler(Move_Completed);
}
private
void
Move_Completed(
object
sender, EventArgs e)
{
//
判断Particle位置是否在父容器内
if
(Canvas.GetLeft(
this
)
>=
(RootWidth
-
this
.Width))
{
Direction
=
-
1
;
}
if
(Canvas.GetLeft(
this
)
<=
0
)
{
Direction
=
1
;
}
//
根据向量设置Particle位置
Canvas.SetLeft(
this
, Canvas.GetLeft(
this
)
+
VectorX
*
Direction);
this
.Move.Begin();
}
}
第三步:新建一个页面,并创建一个Canvas用于承载particle对象,提供加速、减速、改变方向等按钮,用于修改向量的值。代码如下:
oneDimensionalVector.xaml代码
<
Grid
x:Name
="LayoutRoot"
Width
="640"
>
<
Grid.Resources
>
<
Style
x:Key
="ButtonStyle"
TargetType
="Button"
>
<
Setter
Property
="FontFamily"
Value
="Arial,SimSun"
/>
<
Setter
Property
="FontSize"
Value
="12"
/>
<
Setter
Property
="Margin"
Value
="5"
/>
</
Style
>
</
Grid.Resources
>
<
Grid.RowDefinitions
>
<
RowDefinition
Height
="Auto"
/>
<
RowDefinition
Height
="35"
/>
</
Grid.RowDefinitions
>
<
Grid.ColumnDefinitions
>
<
ColumnDefinition
Width
="*"
/>
<
ColumnDefinition
Width
="Auto"
/>
</
Grid.ColumnDefinitions
>
<!--
particle运动容器
-->
<
Canvas
x:Name
="Container"
Height
="20"
Background
="#50000000"
Width
="500"
HorizontalAlignment
="Left"
Margin
="5"
/>
<!--
记录当前小球速度
-->
<
TextBlock
x:Name
="txbVelocity"
Grid.Column
="1"
Grid.RowSpan
="2"
Margin
="5"
/>
<
StackPanel
Orientation
="Horizontal"
Grid.Row
="1"
>
<
Button
x:Name
="start"
Content
="开 始"
Click
="start_Click"
Style
="
{StaticResource ButtonStyle}
"
/>
<
Button
x:Name
="stop"
Content
="停 止"
Click
="stop_Click"
Style
="
{StaticResource ButtonStyle}
"
/>
<
Button
Content
="改变方向"
Click
="Button_Click"
Style
="
{StaticResource ButtonStyle}
"
/>
<
Button
x:Name
="acceleration"
Content
="加 速(+1)"
Click
="acceleration_Click"
Style
="
{StaticResource ButtonStyle}
"
/>
<
Button
x:Name
="decelerate"
Content
="减 速(-1)"
Click
="decelerate_Click"
Style
="
{StaticResource ButtonStyle}
"
/>
</
StackPanel
>
</
Grid
>
在后台代码中,主要用于控制向量的值,使particle可以根据值进行运动。
oneDimensionalVector.xaml.cs 代码
public
partial
class
oneDimensionalVector : Page
{
private
Particle _particle;
public
oneDimensionalVector()
{
InitializeComponent();
Initialize();
}
///
<summary>
///
初始化元素
///
</summary>
private
void
Initialize()
{
_particle
=
new
Particle();
_particle.VectorX
=
1
;
_particle.Direction
=
1
;
_particle.RootHeight
=
Container.Height;
_particle.RootWidth
=
Container.Width;
Canvas.SetLeft(_particle,
2
);
Canvas.SetTop(_particle,
6
);
Container.Children.Add(_particle);
txbVelocity.Text
=
"
速 度:
"
+
_particle.VectorX.ToString();
}
private
void
Button_Click(
object
sender, RoutedEventArgs e)
{
_particle.Direction
=
_particle.Direction
*
-
1
;
}
private
void
stop_Click(
object
sender, RoutedEventArgs e)
{
_particle.Move.Stop();
}
private
void
start_Click(
object
sender, RoutedEventArgs e)
{
_particle.Move.Begin();
}
private
void
acceleration_Click(
object
sender, RoutedEventArgs e)
{
if
(_particle.VectorX
<
20
)
_particle.VectorX
+=
1
;
txbVelocity.Text
=
"
速 度:
"
+
_particle.VectorX.ToString();
}
private
void
decelerate_Click(
object
sender, RoutedEventArgs e)
{
if
(_particle.VectorX
>
1
)
_particle.VectorX
-=
1
;
txbVelocity.Text
=
"
速 度:
"
+
_particle.VectorX.ToString();
}
}
这个代码已经完成.运行效果如图

运行效果演示地址:点击查看
二、使用向量控制对象在二维坐标系中运动
如何让小球可以在二维坐标系中运动?根据上面的代码示例便可以知道,我们只需要再加入用于控制Y轴运动的向量即可。
1.DierctionY 用于控制小球在Y轴运动时候的方向
2.VectorY 用于控制小球在Y轴运动的速度
XAML代码保持不变。
修改后支持二维运动的 Particle.xaml.cs
public
partial
class
Particle : Page
{
//
用于更改在X轴的运动方向
public
int
DirectionX {
get
;
set
; }
//
用于更改在Y轴的运动方向
public
int
DirectionY {
get
;
set
; }
//
存储X轴运动速度
public
double
VectorX {
get
;
set
; }
//
存储Y轴的运动速度
public
double
VectorY {
get
;
set
; }
//
容器大小
public
double
RootHeight {
get
;
set
; }
public
double
RootWidth {
get
;
set
; }
public
Particle()
{
InitializeComponent();
this
.Move.Completed
+=
new
EventHandler(Move_Completed);
}
private
void
Move_Completed(
object
sender, EventArgs e)
{
//
判断在运动到左右两边的时候更改其X轴运动方向
if
(Canvas.GetLeft(
this
)
>=
RootWidth
-
this
.Width)
{
DirectionX
=
-
1
;
}
if
(Canvas.GetLeft(
this
)
<=
0
)
{
DirectionX
=
1
;
}
//
判断在运动到上下两边的时候更改其Y轴运动方向
if
(Canvas.GetTop(
this
)
>=
RootHeight
-
this
.Height)
{
DirectionY
=
-
1
;
}
if
(Canvas.GetTop(
this
)
<=
0
)
{
DirectionY
=
1
;
}
//
根据particle的位置、速度、方向设置其当前位置
Canvas.SetLeft(
this
, Canvas.GetLeft(
this
)
+
VectorX
*
DirectionX);
Canvas.SetTop(
this
, Canvas.GetTop(
this
)
+
VectorY
*
DirectionY);
this
.Move.Begin();
}
}
修改完小球自身代码也要对小球运动容器代码进行修改,使其可以控制小球的Y轴运动
1.首在XAML代码中将Container的高度设置为400,其他参数不变
2.在后台代码加速、减速、改变方向的按钮事件中加入对VectorY和DirectionY的控制代码。
修改后支持二维运动的容器代码
public
partial
class
twoDimensionalVector : Page
{
private
Particle _particle;
public
twoDimensionalVector()
{
InitializeComponent();
Initialize();
}
private
void
Initialize()
{
_particle
=
new
Particle();
_particle.VectorX
=
1
;
_particle.DirectionX
=
1
;
_particle.VectorY
=
1
;
//
初始Y轴速度
_particle.DirectionY
=
1
;
_particle.RootHeight
=
Container.Height;
_particle.RootWidth
=
Container.Width;
Canvas.SetLeft(_particle,
2
);
Canvas.SetTop(_particle,
6
);
Container.Children.Add(_particle);
txbVelocity.Text
=
"
速 度:
"
+
_particle.VectorX.ToString();
}
private
void
Button_Click(
object
sender, RoutedEventArgs e)
{
_particle.DirectionX
*=
-
1
;
_particle.DirectionY
*=
-
1
;
//
控制Y轴方向
}
private
void
stop_Click(
object
sender, RoutedEventArgs e)
{
_particle.Move.Stop();
}
private
void
start_Click(
object
sender, RoutedEventArgs e)
{
_particle.Move.Begin();
}
private
void
acceleration_Click(
object
sender, RoutedEventArgs e)
{
if
(_particle.VectorX
<
20
)
{
_particle.VectorX
+=
1
;
_particle.VectorY
+=
1
;
//
控制Y轴速度,加大
}
txbVelocity.Text
=
"
速 度:
"
+
_particle.VectorX.ToString();
}
private
void
decelerate_Click(
object
sender, RoutedEventArgs e)
{
if
(_particle.VectorX
>
1
)
{
_particle.VectorX
-=
1
;
_particle.VectorY
-=
1
;
//
控制Y轴速度,减小
}
txbVelocity.Text
=
"
速 度:
"
+
_particle.VectorX.ToString();
}
}
修改后的运行效果如下:

运行效果演示地址:点击查看
总结:主要使用向量以及更改向量大小、方向来使得对象可以根据给定的值进行运动,理解向量在动画中的作用以及简单的使用方法。
【注:本文技术论点源于《Foundation Silverlight 3 Animation》,个人理解可能存在差异,请参考原著】