正如你所看到的,Blend是一个很是强大的节约时间的设计工具,在Blend下可以设计出不少满意的动画做品,或许他具体是怎么实现的,经过什么方式实现的咱们仍是一无所知。本篇将续前面几篇基础动画之上,详细介绍Silverlight里提供故事板(StoryBorards)的属性和各类不一样类型的动画(Animations)的详细知识点,揭晓在Blend下设计动画的内幕故事。html
1、故事板(StoryBoard)属性程序员
Silvelight中的故事板(StoryBoard)提供了管理时间线的功能接口,能够用来控制一个或多个Silverlight动画进程,故我也称其为动画时间线容器。以下XAML代码块演示了经过StoryBoard来管理了名为GreenBall的元素在X坐标方向上的偏移变换动画。ide
<
Storyboard
x:Name
="MoveBall"
>
<
DoubleAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="GreenBall"
Storyboard.TargetProperty
="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
>
<
EasingDoubleKeyFrame
KeyTime
="00:00:02"
Value
="540"
/>
</
DoubleAnimationUsingKeyFrames
>
<
/
Storyboard
>
StoryBoard提供了六个经常使用的动画属性选项,它们分别是:AutoReverse,BeginTime,Duration,FillBehavior,RepeatBehavior,SpeedRatio。经过这六个属性能够用来控制动画的基本行为动做,好比想要实现动画的缓冲时间,就须要用到Duration属性;设置动画的开始时间则用BeginTime;若是动画执行完后根据执行路线反向执行到原始状态则须要使用AutoReverse;若是须要设置动画的运行速度则使用SpeedRatio就能够完成。如下代码块演示了AutoReverse属性的使用,动画运行完后将按着原来的运行路线进行反向运行。更多详细可参考这篇博文介绍:《动画基础快速入门Animation》或者MSDN。工具
<
Storyboard
x:Name
="MoveBall"
AutoReverse
="True"
>
<
DoubleAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="GreenBall"
Storyboard.TargetProperty
="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
>
<
EasingDoubleKeyFrame
KeyTime
="00:00:02"
Value
="540"
/>
</
DoubleAnimationUsingKeyFrames
>
</
Storyboard
>
Storyboard的属性是能够组合应用的,如上代码块给动画设置了AutoReverse属性,使其在动画执行完后经过原来的运行路径进行回滚动画,能够给该动画时间线容器添加一个BeginTime属性,使其在程序加载后5秒钟才开始执行动画,这样就使用到了两个属性,以下代码块:post
<
Storyboard
x:Name
="MoveBall"
AutoReverse
="True"
BeginTime
="00:00:05"
>
......
</
Storyboard
>
2、动画类型(Types of animation)动画
Silverlight中的动画主要分From/To/By和关键帧动画两种类型。this
From/To/By动画也称为线性插值动画(Linear Interpolation),是Silverlight类型中最简单的一种动画,只须要设置开始(From)、结束(To)和动画值(By)就能够完成动画的建立,Silverlight 3中提供了三种基础的From/To/By动画类型:DoubleAnimation、ColorAnimation和PointAnimation.url
关键帧动画比From/To/By动画更增强大,无需指定动画的开始、结束以及动画缓冲时间等相关参数,只须要关注关键帧和如何去控制动画就好了。Silverlight 3中提供了四种基本的关键帧动画:缓和(Easing)、线性(Linear)、样条(Spline)和离散(discreet)。spa
DoubleAnimation的使用是很是简单的,只须要搞清楚From/To/By三要素就基本掌握了该类型动画的使用,下面是一个简单的经过DoubleAnimation实现的圆形移动的示例。设计
<
UserControl
x:Class
="DoubleByAnimation.MainPage"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
Width
="800"
Height
="600"
>
<
UserControl.Resources
>
<
Storyboard
x:Name
="Storyboard1"
>
<
DoubleAnimation
Storyboard.TargetName
="Ellipse"
Storyboard.TargetProperty
="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
From
="0"
By
="150"
Duration
="00:00:01"
/>
</
Storyboard
>
</
UserControl.Resources
>
<
Canvas
x:Name
="LayoutRoot"
Background
="White"
>
<
Ellipse
Height
="200"
Width
="200"
Fill
="#FFFF0000"
Canvas.Top
="181"
Canvas.Left
="92"
RenderTransformOrigin
="0.5,0.5"
x:Name
="Ellipse"
>
<
Ellipse.RenderTransform
>
<
TransformGroup
>
<
ScaleTransform
/>
<
SkewTransform
/>
<
RotateTransform
/>
<
TranslateTransform
/>
</
TransformGroup
>
</
Ellipse.RenderTransform
>
</
Ellipse
>
</
Canvas
>
</
UserControl
>
下面经过一个稍复杂的示例来演示DoubleAnimation动画的使用,以下动画代码块实现了名称为Slider对象的X坐标方向的移动动画:
<
Storyboard
x:Name
="SlideOut"
>
<
DoubleAnimation
Storyboard.TargetName
="Slider"
Storyboard.TargetProperty
="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Duration
="00:00:00.50"
To
="150"
/>
</
Storyboard
>
<
Storyboard
x:Name
="SlideIn"
>
<
DoubleAnimation
Storyboard.TargetName
="Slider"
Storyboard.TargetProperty
="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)"
Duration
="00:00:00.50"
To
="0"
/>
</
Storyboard
>
如上动画定义代码块中定义了两个动画,一个实现将对象Slider向X坐标方向移动到150像素点的位置,第二个动画实现将名为Silder的对象向X方向移动到0像素点的坐标位置,这样其实就实现了一个呈现与不呈现的效果。这里咱们发挥大脑的潜力想象一下,若是Slider是一个面板对象,经过鼠标指向和离开的事件使用上面两个动画进行控制其不就实现了面板的鼠标指向就显示,离开就退回到原来的位置了?答案倒是如此,详细见下代码块:
public
partial
class
MainPage : UserControl
{
public
MainPage()
{
InitializeComponent();
Slider.MouseEnter
+=
new
MouseEventHandler(Slider_MouseEnter);
Slider.MouseLeave
+=
new
MouseEventHandler(Slider_MouseLeave);
}
private
void
Slider_MouseLeave(
object
sender, MouseEventArgs e)
{
SlideIn.Begin();
}
private
void
Slider_MouseEnter(
object
sender, MouseEventArgs e)
{
SlideOut.Begin();
}
}

经过上面的示例,是否以为要在Silverlight中实现一个动画是很是简单的?上面的示例就是掩饰了如何使用From/To/By的DoubleAnimation实现了对象的移动动画,一样也可使用关键帧动画(DoubleUsingKeyframes)来实现这一功能。以下代码片断演示了元素Silder向X坐标方向移动到150像素点。
Storyboard MoveRight
=
new
Storyboard();
DoubleAnimationUsingKeyFrames Anim
=
new
DoubleAnimationUsingKeyFrames();
Storyboard.SetTargetName(Anim,
"
Slider
"
);
Anim.SetValue(Storyboard.TargetPropertyProperty,
new
PropertyPath(
"
(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)
"
));
Anim.BeginTime
=
new
TimeSpan(
0
,
0
,
0
);
SplineDoubleKeyFrame SKeyFrame
=
new
SplineDoubleKeyFrame();
SKeyFrame.KeyTime
=
KeyTime.FromTimeSpan(TimeSpan.FromSeconds(
0.5
));
SKeyFrame.Value
=
150
; Anim.KeyFrames.Add(SKeyFrame);
MoveRight.Children.Add(Anim);
......
ColorAnimation类型动画主要应用于颜色上的变换动画效果,好比有一个圆,默认的填充颜色是红色(Red),设计一个动画经过2秒钟的动画换成将圆的填充颜色变换为蓝色。
<
Ellipse
Height
="218"
Width
="218"
Canvas.Left
="294"
Canvas.Top
="195"
Fill
="#FFFF0000"
Cursor
="Hand"
x:Name
="RedEllipse"
/>
能够经过Blend的设计器来完成这样的动画的建立,在对象和时间轴面板里新建动画容器时间线,而后选中RadEllipse圆形对象在0秒的时间线上填充其颜色为红色,2秒的时间线上填充其颜色为蓝色,详细设计以下图:

Blend最终生成的XAML代码以下:
<
Storyboard
x:Name
="Storyboard1"
>
<
ColorAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="RedEllipse"
Storyboard.TargetProperty
="(Shape.Fill).(SolidColorBrush.Color)"
>
<
EasingColorKeyFrame
KeyTime
="00:00:00"
Value
="Red"
/>
<
EasingColorKeyFrame
KeyTime
="00:00:02"
Value
="Blue"
/>
</
ColorAnimationUsingKeyFrames
>
</
Storyboard
>
有Blend这样强大的设计工具是很幸运的,对于设计人员来讲要实现一些动画需求直接经过界面设计就完成了。对于程序员来讲就烦恼了,因为不熟悉设计工具,要实现某种动画只能经过编写程序代码来完成,这将是一个很庞大的工程,好比说当鼠标指向一圆的时候其填充颜色慢慢的向蓝色(Blue)渐变,鼠标离开的时候慢慢的恢复其默认颜色红色。实现这动画效果则须要写上以下长篇的程序代码:
private
Storyboard TurnBlue
=
new
Storyboard();
private
Storyboard TurnRed
=
new
Storyboard();
private
ColorAnimation BlueColor
=
new
ColorAnimation();
private
ColorAnimation RedColor
=
new
ColorAnimation();
public
MainPage()
{
InitializeComponent();
BlueColor.SetValue(Storyboard.TargetNameProperty,
"
RedEllipse
"
);
BlueColor.SetValue(Storyboard.TargetPropertyProperty,
new
PropertyPath(
"
(Shape.Fill).(SolidColorBrush.Color)
"
));
BlueColor.To
=
Colors.Blue;
TurnBlue.Children.Add(BlueColor);
LayoutRoot.Resources.Add(
"
TurnBlue
"
, TurnBlue);
RedColor.SetValue(Storyboard.TargetNameProperty,
"
RedEllipse
"
);
RedColor.SetValue(Storyboard.TargetPropertyProperty,
new
PropertyPath(
"
(Shape.Fill).(SolidColorBrush.Color)
"
))
RedColor.To
=
Colors.Red; TurnRed.Children.Add(RedColor);
LayoutRoot.Resources.Add(
"
TurnRed
"
, TurnRed);
RedEllipse.MouseEnter
+=
(senderRed, eRed)
=>
{
TurnRed.Begin();
};
RedEllipse.MouseLeave
+=
(senderBlue, eBlue)
=>
{
TurnBlue.Begin();
};
}
这样的代码实现其实就是用程序代码建立了两个动画,一个由红色变换到蓝色,一个则由蓝色变换到红色,按照前面的方法直接在Blend中设计也是能够的。最终的运行效果以下图:

PointAnimation类型动画更好理解,也就是动画效果是经过不一样的坐标点来控制的。好比说浪涛的效果,下面就以浪涛为示例来演示PointAnimation类型动画的使用。
代码
<
Storyboard
x:Name
="Storyboard1"
RepeatBehavior
="Forever"
FillBehavior
="HoldEnd"
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point2)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="351.732116699219,36.4064197540283"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="415.732116699219,84.4064178466797"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point3)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="425.502014160156,32.8349914550781"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="489.502014160156,80.8349914550781"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point1)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="499.271911621094,29.2635669708252"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="563.271911621094,77.2635650634765"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point2)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="112.729011535644,80.834991455078"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="104.729011535645,32.8349914550781"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point3)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="185.502014160156,80.834991455078"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="177.502014160156,32.8349914550781"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[1].(BezierSegment.Point1)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="258.275024414062,80.834991455078"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="250.275024414063,32.8349914550781"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point2)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="600.704162597656,72.7879943847655"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="608.704162597656,32.8349229097365"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[2].(BezierSegment.Point3)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="665.502014160156,72.7879943847655"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="673.502014160156,32.8349229097365"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point1)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="730.299926757813,72.7879943847655"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="738.299926757813,32.8349229097365"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point2)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="801.502014160156,40.8349914550781"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="801.502014160156,56.8349229097366"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[3].(BezierSegment.Point3)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="801.502014160156,40.8349914550781"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="801.502014160156,56.8349229097366"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[4].(BezierSegment.Point1)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="801.502014160156,40.8349914550781"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="801.502014160156,56.8349229097366"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.StartPoint)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="1.50201416015619,32.834991455078"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="1.50201416015625,88.8349914550779"
/>
</
PointAnimationUsingKeyFrames
>
<
PointAnimationUsingKeyFrames
BeginTime
="00:00:00"
Storyboard.TargetName
="water"
Storyboard.TargetProperty
="(Path.Data).(PathGeometry.Figures)[0].(PathFigure.Segments)[0].(BezierSegment.Point1)"
>
<
EasingPointKeyFrame
KeyTime
="00:00:00"
Value
="1.50201416015619,32.834991455078"
/>
<
EasingPointKeyFrame
KeyTime
="00:00:03"
Value
="1.50201416015625,88.8349914550779"
/>
</
PointAnimationUsingKeyFrames
>
</
Storyboard
>

关于Silverlight中的动画相关的理论概论暂时就介绍这些,但愿上面的简单介绍能帮助你们深刻的理解和使用Blend进行各类不一样的动画功能设计。更多信息可查阅下面的推资源链接。