Silverlight & Blend动画设计系列十:Silverlight中的坐标系统(Coordinate System)与向量(Vector)运动
如果我们习惯于数学坐标系,那么对于Silverlight中的坐标系可能会有些不习惯。因为在Silverlight中的坐标系与Flash中的坐标系一样,一切都的颠倒的。在标准的数学坐标系中,X轴表示水平轴,Y轴表是垂直轴,然而Silverlight中的坐标系是基于视频屏幕的坐标系。
Silverlight中的坐标系统和Flash中的坐标系统是完全一样的,都是采用笛卡尔坐标系统,分为四象限。简单的说就是以X轴表示水平方向并向东方无限延伸,Y轴表示垂直方向并向着南方无限延伸,X和Y轴相交点表示坐标系源点,其X,Y坐标值为0,0,所以在Silverlight中的坐标系范围就是以坐标源点为起点,无限向东南方向延伸,也就是笛卡尔坐标系中的四象限。
Silverlight的向量(Vector)运动目前仅支持一维向量运动(One-dimensional vector movement)和二维向量运动(Two-dimensional vector movement),也就是平时大家所说的1D和2D。一维向量运动可以理解为在同一直线上的运动,二维向量运动则可以理解在平面空间(X,Y坐标系)里的运动。向量的概念从初中就开始学习,这里就不做介绍了,如有不清楚的朋友可以移步到这里。
二维向量运动很容易理解,在Silverlight的动画设计中二维动画也是最常见和使用率最高的动画,可参考在本系列第一篇《Silverlight & Blend动画设计系列一:偏移动画(TranslateTransform)》中所介绍到的偏移动画变换的实现,其实质就是一个二维向量运动,动画元素对象在动画过度期间不停的改变对象所在的物理坐标位置实现了对象位置的变化,本质上就是元素对象在坐标系里的二维坐标位置的改变。从几何上来理解就是发生了一个二维的向量运动,Silverlight中命名为动画。
/// 创建动画
/// </summary>
private void CreateStoryboard()
{
//元素当前所在的坐标点
Point currentPoint = new Point(Canvas.GetLeft(darkMoon), Canvas.GetTop(darkMoon));
//目标点坐int标
Point point = new Point(280, -245);
//创建动画容器时间线
Storyboard storyboard = new Storyboard();
DoubleAnimation doubleAnimation = new DoubleAnimation();
//创建X轴方向动画
doubleAnimation.From = currentPoint.X;
doubleAnimation.To = point.X;
doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 1));
Storyboard.SetTarget(doubleAnimation, darkMoon);
Storyboard.SetTargetProperty(doubleAnimation,
new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"));
storyboard.Children.Add(doubleAnimation);
//创建Y轴方向动画
doubleAnimation = new DoubleAnimation();
doubleAnimation.SetValue(DoubleAnimation.FromProperty, currentPoint.Y);
doubleAnimation.SetValue(DoubleAnimation.ToProperty, point.Y);
doubleAnimation.SetValue(DoubleAnimation.DurationProperty, new Duration(new TimeSpan(0, 0, 1)));
Storyboard.SetTarget(doubleAnimation, darkMoon);
Storyboard.SetTargetProperty(doubleAnimation,
new PropertyPath("(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)"));
storyboard.Children.Add(doubleAnimation);
storyboard.Begin();
}
下面再来一起学习一个稍微复杂点的二维向量运动,模拟屏幕内有一小球,当鼠标在舞台上点击则小球以动画的形式移动到鼠标点击处。如下XAML定义:
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Canvas x:Name="LayoutRoot" Width="400" Height="400" Background="Black" MouseLeftButtonDown="OnMouseDown">
<Ellipse Fill="YellowGreen" x:Name="ellipse"
Width="20"
Height="20"
Canvas.Left="80"
Canvas.Top="66" >
</Ellipse>
</Canvas>
</UserControl>
其舞台的鼠标左键点击事件代码如下:
{
var mousePoint = e.GetPosition(null);
//当前对象所在坐标
var currentPoint = new Point((double)ellipse.GetValue(Canvas.LeftProperty), (double)ellipse.GetValue(Canvas.TopProperty));
Storyboard sb = new Storyboard();
//创建X坐标方向动画
DoubleAnimation doubleAnimation = new DoubleAnimation();
doubleAnimation.From = currentPoint.X;
doubleAnimation.To = mousePoint.X;
doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 2));
Storyboard.SetTarget(doubleAnimation, ellipse);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Left)"));
sb.Children.Add(doubleAnimation);
//创建Y坐标方向动画
doubleAnimation = new DoubleAnimation();
doubleAnimation.From = currentPoint.Y;
doubleAnimation.To = mousePoint.Y;
doubleAnimation.Duration = new Duration(new TimeSpan(0, 0, 2));
Storyboard.SetTarget(doubleAnimation, ellipse);
Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Top)"));
sb.Children.Add(doubleAnimation);
sb.Begin();
}
以上太阳的简单位置变换移动和小球随鼠标的移动都可以理解为平面中向量的运动,只不过在实现上没有直接通过向量的变换实现,而是通过Silverlight中提供的动画API实现,个人认为,从某种角度可以将Silverlight中的动画API理解为Silverlight的向量API,动画API实现的平面动画理解为向量运动。