公众号推荐
微信公众号搜"智元新知" 关注 微信扫一扫可直接关注哦!
使用 XAML 和 Expression Blend 创建动画
Silverlight
使用 XAML 和 Expression Blend 创建动画
本文将介绍以下内容 :
基本转换和合并的转换
使用触发器和事件
线性关键帧动画和离散关键帧动画
使用 Expression Blend 制作动画
本文使用以下技术: Silverlight 2、Expression Blend
本文基于 Silverlight 2 的预发布版本。文中的所有信息均有可能发生变更。本文是根据 Laurence Moroney 的《Microsoft Silverlight 2 简介,第 2 版》(Microsoft Press,2008)
改编的。
目录
XAML 的一个 巧妙之处 在于:您不仅可以使用 XML 语法声明对象,还可以用同样的方式定义要应用于这些对象的转换。您无需像编程人员一样旋转、移动和倾斜您的对象。并且,通过将动画定义为对象上随时间变化的
属性 ,XAML 还可用于描述如何为对象设置动画
效果 。首先,我将介绍一下各种转换。然后介绍如何将这些转换
添加 到时间线以便为 Silverlight™
内容 设置动画。
转换
在图形字段中,转换可定义如何将点从
一个 坐标空间映射到另
一个 空间中。通常使用转换矩阵来描述转换,转换矩阵是一种特殊的数学构造,
支持 从
一个 系统向另
一个 系统进行简单的数学转换。Silverlight XAML 将此矩阵抽象化,并
支持 旋转、缩放、倾斜和平移(运动)四组转换。Silverlight XAML 还包含另外一种特殊的转换类型,使您可以定义和实现自己的矩阵,然后可使用此矩阵来合并其他转换。
转换是通过转换
属性 应用的。存在的多种不同类型的转换
属性 可应用于不同的对象类型。
@H_
502 _91@
因此,当使用 B
rush 类型时,可以不同的方式定义转换。一种方式是使用 B
rush .Transform
属性 ,这适用于您希望改变画笔
内容 的情况,例如,如果您想先旋转某图像,然后再在 ImageB
rush 中使用该图像。另一种方式是使用 B
rush .RelativeTransform
属性 ,该
属性 允许您使用相对值转换画笔,例如,当使用相同画笔绘制不同大小的区域时,您便可能需要使用相对值转换画笔。
使用 Geometry 类型时,可使用 Geometry.Transform
属性 进行简单转换。但请记住,此类型
不支持 相对转换。
最后,在使用
用户 界面 (UI) 元素时,可指定使用 RenderTransform
属性 进行转换。例如,如果您正在转换
一个 椭圆,可使用 Ellipse.RenderTransform 定义所需的转换。
使用 RotateTransform
属性 进行旋转
通过 RotateTransform,您可以绕指定的中心点将元素旋转
一个 指定的角度。使用 Angle
属性 设置旋转角度以设置您希望将项目旋转多少度。要确定您自己的方向,可将指向右边的水平矢量视为 0 度,若按顺时针旋转,指向下的垂直矢量是旋转 90 度的结果。
可使用 CenterX 和 CenterY
属性 设置转换的中心,从而指定中心点的坐标。
默 认为 0.0,因此
默 认旋转中心点位于容器的
左上角 。
在下面的 XAML 示例中,使用包含指定了 45 度旋转的 RotateTransform 的 RenderTransform 对 TextBlock 进行旋转:
<TextBlock Width="320" Height="40"
Text="This is the text to rotate" textwrap ping="Wrap">
<TextBlock.RenderTransform>
<RotateTransform Angle="45" />
</TextBlock.RenderTransform>
</TextBlock>
在
图 1 中您可以看到,该文本围绕中心点 (0,0)(位于屏幕
左上角 )进行了旋转。
图 1
使用 RotateTransform 属性 (单击图像可查看大图)
下面的 XAML 演示了如何使用 CenterX 和 CenterY 围绕不同点进行旋转。在此示例中,围绕 (100,200) 点进行了旋转:
<TextBlock Width="320" Height="40"
Text="This is the text to rotate" textwrap ping="Wrap" >
<TextBlock.RenderTransform>
<RotateTransform Angle="45" CenterX="100" CenterY="200" />
</TextBlock.RenderTransform>
</TextBlock>
ScaleTransform
属性 用于基于水平轴、垂直轴,或同时基于这两个轴更改对象的大小。如果缩放对象,至少需要指定其中
一个 绕其进行缩放的轴,同时还要指定希望针对该轴缩放的比例。
使用 ScaleX
属性 在水平轴(X 轴)上缩放对象,使用 ScaleY
属性 在垂直轴(Y 轴)上缩放对象。这两个
属性 均设置为双精度值,该值代表在指定轴上将对象的当前大小与其相乘的值。因此,大于 1 的值可使对象扩大相应的倍数。例如,ScaleX 值为 2 可使该对象的水平大小加倍。大于 0 小于 1 的值将使对象缩小。例如,设置为 0.5 会使对象在指定维度上的大小减小一半。
例如,下面的 XAML 将创建
一个 宽 96 像素、高 88 像素的红色矩形:
<Rectangle Fill="#FFFF0404 " stroke ="#FF000000"
Width="96" Height="88"
Canvas.Left="112" Canvas.Top="72" />
图 2 演示了此对象在 Silverlight 中呈现时的外观。
图 2
呈现矩形 (单击图像可查看大图)
要对此对象应用 ScaleTransform,可使用 RenderTransform 并将转换指定为 ScaleTransform。XAML 如下:
<Rectangle Fill="#FFFF0404 " stroke ="#FF000000"
Width="96" Height="88" Canvas.Left="112" Canvas.Top="72">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="2" />
</Rectangle.RenderTransform>
</Rectangle>
如果您熟悉编码,您会发现,使用 ScaleTransform,该矩形在水平上的大小扩展到了右侧。这是因为未指定缩放中心。您可以使用 CenterX
属性 进行水平缩放或使用 CenterY
属性 进行垂直缩放来指定缩放中心。这两个
属性 指定缩放中心的坐标。请注意,此坐标是相对于矩形
左上角 的。此外,
默 认坐标为 0,表示缩放会发生在水平轴的右侧和垂直轴的下侧。
如果将 CenterX
属性 设置为正值(例如,50),则将绕 X 点将此矩形的最左端向右缩放 50 像素。这看起来像是 CenterX 未更改位置而矩形向左移动了一定的像素数(此大小取决于比例因子的大小)。这是因为拉伸是以该点为中心进行的,将此矩形的左侧向左推而将其右侧向右推。您可以利用相同的方式设置 ScaleY 和 CenterY 值以获得相似的
效果 :
<Rectangle Fill="#FFFF0404 " stroke ="#FF000000"
Width="96" Height="88"
Canvas.Left="80" Canvas.Top="80">
<Rectangle.RenderTransform>
<ScaleTransform ScaleX="2"
CenterX="50"/>
</Rectangle.RenderTransform>
</Rectangle>
使用 TranslateTransform
属性 移动对象
平移是指在二维平面上将对象从
一个 位置移动到另
一个 位置的一种转换。可通过设置定义对象沿其 X 轴和 Y 轴移动的矢量来定义平移。可使用转换中的 X
属性 和 Y
属性 设置这些矢量。要将项目水平向右移动两个单位,可将 X
属性 设置为 2,要将其水平向左移动,可使用负值,例如 -2。同样,要垂直移动对象,可使用 Y
属性 ,使用正值可使此对象向屏幕下方移动,而使用负值可使对象向屏幕上方移动。
下面是
一个 平移示例:通过指定 X 和 Y 值,将我们前面看到的红色矩形的位置向左上方移动。这些值有效地构成确定该平移的矢量:
<Rectangle Fill="#FFFF0404 "
stroke ="#FF000000"
Width="96" Height="88"
Canvas.Left="80" Canvas.Top="80">
<Rectangle.RenderTransform>
<TranslateTransform X="-50" Y="-50"/>
</Rectangle.RenderTransform>
</Rectangle>
结果如
图 3 所示。与
图 2 中矩形的位置相比,此矩形已移动到相对于该指定位置的左上方。
图 3
使用 TranslateTransform 属性 (单击图像可查看大图)
倾斜对象
包括 沿某一轴以渐进、统一的方式进行更改。这会产生将
一个 正方形或矩形变成平行四边形的
效果 。在二维表面上创建深度
效果 时这种视觉
效果 很有用。
您可以围绕
一个 中心点沿 X 轴或 Y 轴倾斜一定的角度。当然,这两种方式可以合并起来使用,这样您就可以同时沿两个轴进行倾斜。以下 XAML 可将矩形沿 X 轴倾斜 45 度:
<Rectangle Fill="#FFFF0404 " stroke ="#FF000000"
Width="96" Height="88"
Canvas.Left="80" Canvas.Top="80">
<Rectangle.RenderTransform>
<SkewTransform AngleX="45"/>
</Rectangle.RenderTransform>
</Rectangle>
结果如
图 4 所示。
图 4
使用 SkewTransform 倾斜矩形 (单击图像可查看大图)
倾斜对于在图形中模拟三维
效果 很有帮助。例如,您可以将 SkewTransform 应用到三个相邻矩形(两个沿 X 轴倾斜,
一个 沿 Y 轴倾斜)来创建
一个 三维透视
效果 (请参见
图 5 )。
图 5
使用三个倾斜的矩形模拟透视效果 (单击图像可查看大图)
使用 MatrixTransform 定义转换
从本质上来说,所有转换都是通过将对象的坐标空间与转换矩阵相乘来执行的。到目前为止,您所看到的每
一个 转换都是我们熟知且定义明确的转换。矩阵数学和如何实现转换都超出了本文所要讨论的范围,但是为了语法的完整性,我将介绍如何在 Silverlight XAML 中定义它们。
请注意,MatrixTransform 中所用的矩阵都是仿射矩阵,这意味着此矩阵的最后一行始终设置为 (0 0 1),这样您仅需设置前二列。可使用转换的 Matrix
属性 设置这些矩阵,该
属性 采用包含以空格分隔的前两行值的字符串。
<Rectangle Fill="#FFFF0404 "
stroke ="#FF000000"
Width="96" Height="88"
Canvas.Left="80" Canvas.Top="80">
<Rectangle.RenderTransform>
<MatrixTransform Matrix="1 0 1 2 0 1"/>
</Rectangle.RenderTransform>
</Rectangle>
使用此矩阵进行转换的
效果 是呈现
一个 经过拉伸和倾斜双重转换的矩形。
合并转换
在上例中您可以看到,通过使用转换仿射矩阵及指定使用 MatrixTransform 类型可以创建复杂的转换。但是,如果您不是矩阵数学方面的专家,就需要适用于使用转换的另一项技术,即通过 TransformGroup 元素将上述两步合并。这样,您只需要指定多个转换,并将每个转换的合并
效果 都应用到此对象即可。以下是
一个 示例:
<Rectangle Fill="#FFFF0404 " stroke ="#FF000000"
Width="96" Height="88"
Canvas.Left="80" Canvas.Top="80">
<Rectangle.RenderTransform>
<TransformGroup>
<ScaleTransform ScaleX="1.2" ScaleY="1.2" />
<SkewTransform AngleX="30" />
<RotateTransform Angle="45" />
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
此示例中合并了
一个 ScaleTransform,该
效果 将图形的大小在两个轴上各
增加 20%,在 X 轴上倾斜 30 度并旋转 45 度。
“动画”字面上的意思是指“为某物赋与生命”。因此,借助动画,您可以通过在一段时间内或响应
用户 操作而更改对象的
属性 (如颜色、大小、不透明度及其他
属性 )来为自己的作品带来生命力。
在 XAML 中,可通过随着时间更改项目的
一个 或多个
属性 为其设置动画
效果 。此时间是使用时间线定义的。例如,要在 5 秒内将项目移过屏幕,应将时间线指定为 5 秒,设置 Canvas.Left
属性 在此时间内从 0 变为屏幕宽度的动画
效果 。在下面的部分中,我将介绍每种可用的动画类型,以及使用关键帧设置这些
属性 的动画
效果 时的区别。
在了解不同的动画类型之前,您应该知道动画的框架中
包括 Trigger、EventTrigger 和 Storyboard。但是,首先我将介绍以下基本概念,然后再详细讲解不同的动画类型。
使用触发器和事件触发器
Silverlight 中的动画为了响应使用触发器定义的事件而发生。目前,Silverlight XAML 中仅
支持 一种触发器类型,即 EventTrigger。每个 UI
属性 都具有
一个 Triggers 集合,用来定义
一个 或多个触发器(即
一个 或多个 EventTrigger)。
因此,将动画
添加 到元素的第一步是定义其 Trigger 集合;然后需要向您已创建的集合中至少
添加 一个 EventTrigger。例如,如果您正在为
一个 矩形设置动画,第一步(指定 Triggers 集合)应如下所示:
<Rectangle x:Name="rect" Fill="Red"
Canvas.Top="100" Canvas.Left="100"
Width="100" Height="100">
<Rectangle.Triggers>
</Rectangle.Triggers>
</Rectangle>
接下来,您需要定义
一个 EventTrigger 并将其
添加 到此集合。
在这 个 EventTrigger 中,使用 RoutedEvent
属性 指定动画运行所响应的事件。请注意,RoutedEvent 仅
支持 Loaded 事件。
要实现加载矩形时开始的动画,应指定 EventTrigger,如下所示:
<EventTrigger RoutedEvent="Rectangle.Loaded">
</EventTrigger>
运行此动画的 XAML
代码 段如下所示:
<Rectangle x:Name="rect" Fill="Red" Canvas.Top="100"
Canvas.Left="100" Width="100" Height="100">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
下
一个 步骤是定义您希望使用的动画。动画包含在 Storyboards 内。
使用 BeginStoryboard 和 Storyboard
BeginStoryboard 是
一个 包含 Storyboard 对象的触发器操作。Storyboard 对象包含动画定义。当定义动画时,您只需在 EventTrigger 定义内嵌入这些对象。以下
代码 通过矩形示例演示了如何实现此操作:
<Rectangle x:Name="rect" Fill="Red"
Canvas.Top="100" Canvas.Left="100"
Width="100" Height="100">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
定义动画参数
现在动画的框架已建立,您可以指定希望执行的动画。从最根本上来讲,动画是定义如何随时间更改某个
属性 。您可为三种不同的
属性 类型设置动画
效果 。其中的每个
属性 类型从 From
属性 中指定的值(如果尚未设置,则使用当前值)开始设置动画
效果 ,到 To
属性 中指定的值结束或者到 By
属性 中指定的值结束。
Double 类型 使用 DoubleAnimation 或 DoubleAnimationUsingKeyFrames 为其设置动画
效果 。此
方法 用于为包含双精度值的
属性 (例如,Canvas.Left 等维度
属性 或不透明度等可视化
属性 )设置动画
效果 。
Point 类型 使用 PointAnimiation 或 PointAnimationUsingKeyFrames 类型为其设置动画
效果 。此特定
方法 用于为包含点值的
属性 (例如使用点定义的线段或曲线)设置动画
效果 。
Color 类型 使用 ColorAnimation 或 ColorAnimationUsingKeyFrames 类型动画为其设置动画
效果 。此
方法 用于为包含颜色值的
属性 (例如元素的背景或笔画)设置动画
效果 。
要定义您希望对其应用动画的对象,可
在这 些动画类型中使用 Storyboard.TargetName
属性 ,并将目标对象的
名称 传递给该
属性 (此
名称 在该对象上使用 x:Name
属性 进行设置)。另外,还需要使用 Storyboard.TargetProperty 指定要对其设置动画
效果 的
属性 。请注意,如果要指定复杂
属性 或附加
属性 (如 Canvas.Left),应将其放在括号内。因此,举例来说,要指定 Double 动画
效果 以对名为 rect 的矩形使用 Canvas.Left
属性 ,所得到的 XAML 如下所示:
<DoubleAnimation Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)" />
要定义将目标
属性 从
一个 值转换到另
一个 值所用的时间,可使用 Duration
属性 。请注意,此
属性 定义为 HH:MM:SS 格式,例如,如果动画的持续时间为 5 秒,则指定为 00:00:05,缩写为 0:0:5。
<DoubleAnimation Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)" Duration="0:0:5" />
如果您不希望动画立即开始,可使用 BeginTime
属性 和相同的语法插入延迟:
@H_30_
404 @<DoubleAnimation Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)" BeginTime="0:0:5" />
您还可以通过将持续时间与对比速率相乘来调整动画行为。可使用 Spee
drat io
属性 完成此操作。例如,上一示例将持续时间设置为 5 秒。您可以通过将 Spee
drat io 设置为 2 来更改对比速率,使该动画持续 10 秒;或者通过将 Spee
drat io 设置为 0.2 来加快动画的速度,使动画在 1 秒内完成。
<DoubleAnimation Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)"
Speedrat io="2" Duration="0:0:5" />
Silverlight 动画提供了一项
功能 ,可以撤消对部分动画所作的更改。例如,如果在特定的时间内将双精度值从 0 移动至 500,AutoReverse 会使动画从 500 移回 0。
请注意,如果动画原来设置为运行 5 秒,并且 AutoReverse 设置为 true,则完整的动画需要持续 10 秒。下面是
一个 包含 AutoReverse
属性 的 XAML 示例:
<DoubleAnimation Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)"
AutoReverse="True"
Duration="0:0:5" />
运行完动画后,您可以应用大量选项控制动画,使动画以您所希望的方式运行。可使用 RepeatBehavior
属性 指定这些选项。此
属性 可以采用三种不同类型的值:
以秒为单位定义的时间。时间线会等待这段时间过后再次演示动画。
为实现不断重复而设置为 Forever 的重复行为。
通过指定后面带有 x 的数字设置的离散重复数。例如,如果您希望该动画运行 3 次,则指定值 3x。
图 6 演示了一段完整的 XAML,可以将设置动画
效果 的矩形从 X 轴上的 100 移动至 500,再移回 100,然后将此行为重复 3 次:
图 6 撤消和重复动画
<Rectangle x:Name="rect" Fill="Red"
Canvas.Top="100" Canvas.Left="100"
Width="100" Height="100">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation RepeatBehavior="3x"
Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)"
To="500" Duration="0:0:5"
AutoReverse="True" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
让我们稍微详细地介绍一下其中的每个动画类型。首先,我会介绍设置各种类型的动画分别需要的
属性 ,然后介绍与图像想适应的相关动画关键帧类型。
使用 DoubleAnimation 设置值动画
效果
利用 DoubleAnimation 对象,您可以在指定的时间线范围内指定双精度值的更改方式。动画会随着时间作为
属性 值
间的 线性插值进行计算。
设置双精度值动画
效果 时,可以在动画开始时使用 From 值指定该值,然后将其更改为 To 值(绝对目标),或更改为 By 值(相对目标)。例如,如果要将某个项目的 Canvas.Left
属性 从 100(接近屏幕的左端)移动至 500,您可以将 From 值设置为 100,将 To 值设置为 500 或将 By 值设置为 400。请注意,如果您同时设置了 To 值和 By 值,则优先采用 To
属性 ,而忽略 By
属性 。同样,如果此矩形已经位于 From 的目标位置,则不需要再指定 From
属性 。
上
一个 XAML 示例演示了此行为。此矩形位于 Canvas.Left 值为 100 的位置,而 DoubleAnimation 将 To 值指定为 500。因此,该动画会将该值从 100 移动至 500,这将使此矩形一直移动到屏幕的右侧。
使用 ColorAnimation 设置颜色动画
效果
ColorAnimation 的使用方式与 DoubleAnimation 类似。您可以使用它指定元素的颜色值如何随时间更改。这样,动画会在指定的时间内作为颜色值
间的 线性插值进行计算。
设置颜色动画
效果 时,可以在动画开始时使用 From
属性 指定该值。如果不指定此值,则会使用当前的颜色。可使用 To
属性 指定所需的结束颜色。还可以指定 By
属性 ,它提供的结束颜色是将 From 颜色(或开始颜色)值与 By 颜色值相加的最终结果。
在您为基于颜色的
属性 设置动画
效果 时,不要直接为该
属性 的
内容 设置动画
效果 ,因为该
属性 的
内容 通常是画笔而不是颜色。因此,举例来说,如果您希望使某个矩形的填充颜色具有动画
效果 ,就不应将此矩形的 Fill
属性 作为目标
属性 ,而应指定用于执行填充行为的 SolidB
rush 的 Color
属性 。
图 7 中的示例演示了如何使矩形的颜色具有动画
效果 :使用颜色动画,在 5 秒内将该矩形的颜色由黑色变为白色。在
代码 中您可以看到,此 XAML
代码 段指定了 SolidColorB
rush 的 Color
属性 ,从而以目标
属性 填充了该图形。请注意,这是
解决 类似这种情况中复杂
属性 所使用的典型 XAML 语法。
图 7 设置颜色更改的动画
效果
<Rectangle x:Name="rect" Canvas.Top="100"
Canvas.Left="100" Width="100"
Height="100" Fill="Black">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Storyboard.TargetName="rect"
Storyboard.TargetProperty=
"(Shape.Fill).(SolidColorBrush .Color)"
To="#00000000" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
使用 PointAnimation 设置点的动画
效果
要更改随时间而定义为点的值,需要使用 PointAnimation 类型。这样,动画会在指定的时间内作为两个值之
间的 线性插值进行计算。
与设置 Color 和 Double 动画
效果 的
方法 类似,您可以使用 From 指定开始值,使用 By 将目标指定为相对方向,或使用 To 将目标指定为绝对点。
图 8 中的示例演示了如何使贝塞尔曲线的终点具有动画
效果 。在此示例中,该贝塞尔曲线将起点定义在 (100,100),终点定义在 (300,100),控制点定义在 (200,0)。动画设置为在加载该曲线后触发,设置该曲线的终点 (Point2) 从 (300,100) 更改为 (300,600) 的动画
效果 的持续时间为 5 秒。
图 8 使曲线的终点具有动画
效果
<Path stroke ="Black" >
<Path.Data>
<PathGeometry>
<Pathfig ure StartPoint="100,100">
<Quadrat icBezierSegment x:Name="seg"
Point1="200,0" Point2="300,100" />
</Pathfig ure>
</PathGeometry>
</Path.Data>
<Path.Triggers>
<EventTrigger RoutedEvent="Path.Loaded">
<BeginStoryboard>
<Storyboard>
<PointAnimation Storyboard.TargetName="seg"
Storyboard.TargetProperty="Point2"
From="300,100" To="300,600" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Path.Triggers>
</Path>
使用关键帧
您刚刚了解的三种动画类型:ColorAnimation、DoubleAnimation 和 PointAnimation,全部是通过使用线性插值随时间更改定义的
属性 来完成的。例如,如果您将
一个 双精度值在 5 秒内从 100 移动至 500,则它会以每秒 80 的速度增长。
这三种动画类型中的任意一种都可以通过一组称为里程碑的关键帧对此转换进行定义。要将动画的线性行为从开始
属性 更改为结束
属性 ,只需插入
一个 或多个关键帧。然后
在这 些不同的点之间定义希望的动画类型。
使用关键时间对关键帧进行定义。这些时间是相对于动画的开始时间指定的;它们同样可以指定关键帧的结束时间。例如,如果在 9 秒长的动画中需要设置 3 个间隔均匀的关键帧,您可以指定第
一个 关键帧在 0:0:3 结束,第二个在 0:0:6 结束,第三个在 0:0:9 结束。请记住,您不需要指定关键时
间的 长度,而要指定每个关键帧的结束时间。
来看另
一个 示例,假设
一个 Double 动画,您希望其横跨从 100 到 500 的前后两个部分。该动画应在前半部分
快速 移动,而在后半部分缓慢移动。但首先,它总共需要 6 秒的
转换时间 。因为 350 是 100 和 500 之
间的 中点,因此应定义
一个 从点 350 开始的关键帧。使用关键时间 0:0:1 将该关键帧设置为在起点和中间点之间持续 1 秒,然后使用第二个关键时间 0:0:6 将中点和终点之
间的 持续时间设置为 5 秒。现在项目被设置为飞快移动到屏幕中的中点,然后慢吞吞地行进过其余路程。
在上一示例中,两个设置动画
效果 的部分都将以线性方式插入。要
显示 其他的灵活性,则需要提供另外两种类型的关键帧:立即从两值之
间的 值跳过的离散关键帧,和使用二次曲线移过起点和终点之
间的 值以定义插值的样条关键帧。(在后面部分中,您将看到如何使用关键帧为 Double 类型定义动画。请注意,该原理同样适用于 Point 动画类型和 Color 动画类型。)
要指定关键帧,应在动画中使用 UsingKeyFrames 后缀。这就是说,若要既定义 Double 动画又使用关键帧,需要在指定目标和
属性 的对象中使用 DoubleAnimationUsingKeyFrames(与使用 DoubleAnimation 的
方法 相同)。DoubleAnimationUsingKeyFrames 包含了对关键帧的定义。(我以前提到过,这同样适用于 PointAnimationUsingKeyFrames 或 ColorAnimationUsingKeyFrames。)
使用线性关键帧
在两个
属性 值之间设置动画的
默 认
方法 是使用线性插值,其中的数值将随时间均匀分配。您同样可以使用 LinearKeyFrame 类型定义帧之
间的 线性步骤,LinearKeyFrame 类型也使用线性插值,但它用于关键帧之间,这样您便可以设置加速或减速
效果 。
请仔细观察
图 9 中第一部分
显示 的动画
代码 。此处使用了 DoubleAnimationUsingKeyFrames,它定义了两个关键帧。其中
一个 为在 1 秒内的 Canvas.Left 更改定义了 0 至 300
间的 线性插值,而另
一个 为在 8 秒内的 Canvas.Left 更改定义了 300 至 600
间的 线性插值。这会使矩形产生
快速 移动到中点,然后缓慢地移动过其余路程的
效果 。相似的原理同样适用于 LinearPointKeyFrame 和 LinearColorKeyFrame。
图 9 具有关键帧的动画
线性插值
<Rectangle Fill="#FFFF0000" stroke ="#FF000000"
Width="40" Height="40"
Canvas.Top="40" x:Name="rect">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)" >
<LinearDoubleKeyFrame KeyTime="0:0:1" Value="300" />
<LinearDoubleKeyFrame KeyTime="0:0:9" Value="600" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
离散关键帧
<Rectangle Fill="#FFFF0000" stroke ="#FF000000"
Width="40" Height="40"
Canvas.Top="40" x:Name="rect">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="rect"
Storyboard.TargetProperty="(Canvas.Left)" >
<dis creteDoubleKeyFrame KeyTime="0:0:1" Value="300" />
<dis creteDoubleKeyFrame KeyTime="0:0:9" Value="600" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
使用离散关键帧
如果希望将
属性 从
一个 值更改为另
一个 值,但不希望使用线性插值,则可以使用离散关键帧。这可以使对象跳至指定关键帧时间处的值。
图 9 的第二部分演示了与上一部分相同的示例,只是使用了离散关键帧。进入动画 1 秒后,该矩形将跳过屏幕一半路程。进入动画九秒后,它将跳至屏幕右端。请注意,相似的原理同样适用于
dis cretePointKeyFrame 和
dis creteColorKeyFrame。
使用样条关键帧
要使用提供加速和减速
效果 的曲线值将
属性 从
一个 值更改为另
一个 值,可使用样条关键帧。为此,您首先要定义一条二次贝塞尔曲线,然后该
属性 从
一个 值移动到另
一个 值的速度由该曲线的并行投影确定。
如果感觉太抽象,请考虑以下情形:太阳正位于头顶,您将
一个 棒球击打到外场。您注视着该棒球的影子。棒球向空中上升时,其影子像是在加速移动。当它到达顶点时,您可以看到影子在减速。当球落下时,您会看到影子再次加速,直到它被某个人接住或者落到地面上。
在本示例中,将您的动画想象为球的影子,而将样条想象成棒球的运动曲线。使用 KeySpline 定义棒球的轨迹(一条样条)。KeySpline 定义二次贝塞尔曲线的控制点。将其具体化,以使曲线的第一点位于 0,第二点位于 1。为了得到棒球运动轨迹遵循的抛物线圆弧,KeySpline 需要包含两个以逗号分隔的具体化值。
要定义一条曲线(如棒球的飞行轨迹),可以使用 KeySpline(如 0.3,0 0.6,1)指定样条。0.3,1 将曲线的第
一个 点定义在 (0.3,0),而第二个点定义在 (0.6,1)。这将产生的动画
效果 是:在棒球完成大约三分之一的运动轨迹前迅速加速;接着,在棒球到达三分之二的轨迹前匀速移动;然后,设置动画
效果 的棒球会减速完成余下的飞行轨迹,模拟棒球落到地面上的运动。
图 10 中的示例演示如何使用 KeySpline 来定义使用 DoubleAnimationUsingKeyFrames 的此模拟中的样条。此示例为椭圆设置了动画
效果 ,这样它在屏幕上的移动方式类似于棒球的影子,就像当棒球在空中飞行时,从棒球上方向下看时所看到的地面上的情况。
图 10 使用 KeySpline 定义样条
<Ellipse Fill="a#FF444444" stroke ="#FF444444"
Width="40" Height="40"
Canvas.Top="40" x:Name="ball">
<Ellipse.Triggers>
<EventTrigger RoutedEvent="Ellipse.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetName="ball"
Storyboard.TargetProperty="(Canvas.Left)" >
<SplineDoubleKeyFrame KeyTime="0:0:5"
KeySpline="0.3,1" Value="600" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Ellipse.Triggers>
</Ellipse>
动画和 Expression Blend
可以在 Expression Blend™ 中以图形的方式定义动画。这会
生成 执行该动画的 XAML,从而
自动 为您提供不同类型的动画。
使用 Expression Blend 时,请从“窗口”
菜单 选择“动画工作区”。这将为您提供以图形方式设计时间线的工具,当您编辑希望使用可视编辑器更改的
属性 时,会
生成 该动画的 XAML
代码 。
在屏幕的
底部 ,您可以看到“对象和时间线”视图。这使您可以
添加 时间线,然后以可视的方式
添加 关键帧。要
添加 新时间线,请单击“对象和时间线”视图中的“+”按钮。
单击“+”按钮时,您将看见
一个 “创建 Storyboard”对话框,要求您输入要创建的 Storyboard 的
名称 。在本例中,我已将
默 认
名称 从 Storyboard1 更改为 Timeline1,并取消选中“创建为资源”复选框。
使用 Expression Blend 时,可在画布级别创建动画,或者将动画创建为资源。在前一种情况下,动画接着运行以响应画布上的触发器。以下是
一个 由 Blend 通过“创建 Storyboard”创建的 XAML 的示例,
用户 在此 XAML 中指定了他们不希望将动画创建为资源:
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.Loaded">
<BeginStoryboard>
<Storyboard x:Name="Timeline1"/>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
请注意,如果
用户 选中了“创建为资源”复选框,则将在 <Canvas.Resources> 内部创建 Storyboard,然后您必须从 JavaScript 中运行它。
“对象和时间线”视图将更改为
显示 刚刚创建的时间线。您可以在
图 11 的
底部 看到该时间线。时间线中时间 0 处的垂直线指示当前时间。(在 Expression Blend 中,此线呈黄色。)要
添加 关键帧,只需将此线拖动到希望设置关键帧的地方,然后单击“记录关键帧”按钮。此按钮位于 0:00:000 的左边的时间轴的正上方。
图 11
Expression Blend 动画工作区 (单击图像可查看大图)
将此线拖动到 4 秒
标记 处,然后
添加 一个 关键帧。您会看到该关键帧
添加 为时间线上的
一个 小椭圆形。现在时间线位于 4 秒帧上,并且已
添加 了
一个 关键帧,您可以编辑矩形的颜色、位置、不透明度或者形状,而 Blend 将计算实现该动画所需的正确转换。最后,您可能注意到,如果来回拖动该时间线指示器,您可以预览该动画并查看它在任一特定时
间的 状态。
在本文中,我介绍了如何在 Silverlight XAML 定义转换和动画。我向您介绍了旋转、缩放或者倾斜对象所使用的不同类型的转换,以及应用到图形时使用仿射矩阵的任意形式的转换。然后,我对动画进行了概述,并向您介绍如何定义基于 XAML 触发器运行的动画。您看到了动画如何随时间更改
属性 值,并看到了可为双精度值、点和颜色设置动画
效果 的 XAML 类型。随后我介绍了如何使用关键帧更好地控制您的动画。最后,我向您介绍了 Expression Blend 动画设计器,您可以看到如何轻松地使用 Expression Blend 以可视方式
生成 动画。
Laurence Moroney 是 Microsoft 的一位高级技术推广人员,专门研究 Silverlight。他著有多部有关计算
主题 (
包括 Silverlight、AJAX、互操作性和安全性)的书籍。您可以通过
blogs.msdn.com/webnext 访问 Laurence 的
博客 。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。