正如你所看到的,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進行各類不一樣的動畫功能設計。更多信息可查閱下面的推資源鏈接。