分鏡腳本概觀
本主題說明如何使用 Storyboard 物件來組織和套用動畫。 它描述如何以互動方式操作 Storyboard 物件,並描述間接屬性目標語法。
必要條件
若要了解本主題,您應該熟悉不同的動畫類型及其基本功能。 如需動畫的簡介,請參閱動畫概觀。 您也應該了解如何使用附加屬性。 如需附加屬性的詳細資訊,請參閱附加屬性概觀。
什麼是分鏡腳本
動畫不是唯一有用的時間軸型別。 還有其他時間軸類別可以協助您組織時間軸集合,以及將時間軸套用至屬性。 容器時程表衍生自 TimelineGroup 類別,並包含 ParallelTimeline 和 Storyboard 。
Storyboard是一種容器時程表類型,可提供其包含之時間軸的目標資訊。 分鏡腳本可以包含任何類型的 Timeline ,包括其他容器時程表和動畫。 Storyboard 物件可讓您將影響各種物件和屬性的時程表合併成單一時間軸樹狀結構,讓您輕鬆地組織和控制複雜的計時行為。 例如,假設您想讓按鈕執行下列三個動作。
在使用者選取按鈕時放大及變更色彩。
按一下按鈕時縮小再放大回原本大小。
在停用時縮小並淡化到 50% 的不透明度。
在此案例中,您有多組套用至同一個物件的動畫,並且想要視按鈕的狀態在不同時間播放。 Storyboard 物件可讓您組織動畫,並將其套用到一或多個物件群組中。
您可以在何處使用分鏡腳本
Storyboard可用來建立可動畫類別之相依性屬性的動畫效果(如需讓類別產生動畫效果的詳細資訊,請參閱 動畫概觀 )。 不過,由於分鏡腳本是架構層級的功能,因此物件必須屬於 NameScope 或 FrameworkContentElement 的 FrameworkElement 。
例如,您可以使用 Storyboard 來執行下列動作:
以動畫顯示 SolidColorBrush 繪製按鈕背景的 (非架構元素)(類型 FrameworkElement 為 ),
以動畫顯示 SolidColorBrush (非架構專案) 繪製使用 Image ( FrameworkElement ) 所顯示的填滿 GeometryDrawing (Non-framework 元素)。
在程式碼中,如果 SolidColorBrush 向該 註冊其名稱 FrameworkElement ,則以類別宣告 FrameworkElement 的 動畫 SolidColorBrush 。
不過,您無法使用 Storyboard 以動畫顯示 SolidColorBrush 未向 FrameworkElement 或 FrameworkContentElement 註冊其名稱的 ,或 未用來設定 或 FrameworkContentElement 的屬性 FrameworkElement 。
如何以分鏡腳本套用動畫
若要使用 Storyboard 來組織和套用動畫,您可以將動畫新增為 的 Storyboard 子時間軸。 類別 Storyboard 會提供 Storyboard.TargetName 和 Storyboard.TargetProperty 附加屬性。 您可以設定動畫的這些屬性以指定其目標物件和屬性。
若要將動畫套用至其目標,您可以使用觸發程式動作或方法開始 Storyboard 。 在 XAML 中,您會使用 BeginStoryboard 物件搭配 EventTrigger 、 Trigger 或 DataTrigger 。 在程式碼中,您也可以使用 Begin 方法。
下表顯示支援每個 Storyboard 開始技術的不同位置:每個實例、樣式、控制項範本和資料範本。 「每個執行個體」指的是將動畫或分鏡腳本直接套用至物件之執行個體,而非樣式、控制項範本或資料範本的技術。
開始分鏡腳本的方法… | 每個執行個體 | 樣式 | 控制項範本 | DataTemplate \(英文\) | 範例 |
---|---|---|---|---|---|
BeginStoryboard 和 EventTrigger | Yes | Yes | Yes | Yes | 使用分鏡腳本建立屬性的動畫 |
BeginStoryboard 和 屬性 Trigger | No | 是 | Yes | Yes | 在屬性值變更時觸發動畫 |
BeginStoryboard 和 屬性 MultiTrigger | No | 是 | Yes | Yes | MultiTrigger 類別範例 |
BeginStoryboard 和 DataTrigger | No | 是 | Yes | Yes | 操作說明︰在資料變更時觸發動畫 |
BeginStoryboard 和 MultiDataTrigger | No | 是 | Yes | Yes | MultiDataTrigger 類別範例 |
Begin 方法 | 是 | 否 | No | No | 使用分鏡腳本建立屬性的動畫 |
下列範例會使用 Storyboard ,以動畫顯示 Width 元素的 Rectangle ,以及 ColorSolidColorBrush 用來繪製該 Rectangle 的 。
<!-- This example shows how to animate with a storyboard.-->
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.Samples.Animation.StoryboardsExample"
WindowTitle="Storyboards Example">
<StackPanel Margin="20">
<Rectangle Name="MyRectangle"
Width="100"
Height="100">
<Rectangle.Fill>
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
</Rectangle.Fill>
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Width"
From="100" To="200" Duration="0:0:1" />
<ColorAnimation
Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color"
From="Blue" To="Red" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Data;
using System.Windows.Shapes;
using System.Windows.Input;
namespace Microsoft.Samples.Animation
{
public class StoryboardsExample : Page
{
public StoryboardsExample()
{
this.WindowTitle = "Storyboards Example";
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(20);
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "MyRectangle";
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
myRectangle.Fill = mySolidColorBrush;
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 100;
myDoubleAnimation.To = 200;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.Red;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
myStoryboard.Children.Add(myColorAnimation);
myRectangle.MouseEnter += delegate(object sender, MouseEventArgs e)
{
myStoryboard.Begin(this);
};
myStackPanel.Children.Add(myRectangle);
this.Content = myStackPanel;
}
}
}
下列各節將更詳細地描述 TargetName 和 TargetProperty 附加屬性。
以架構元素、架構內容元素和 Freezable 為目標
上一節提到,動畫若要尋找其目標,它必須知道目標的名稱和要建立動畫的屬性。 指定要產生動畫效果的屬性是直接的:只要以屬性的名稱設定 TargetProperty
動畫即可。 您可以藉由在動畫上設定 Storyboard.TargetName 屬性來指定物件的名稱,其屬性要產生動畫效果。
警告
雖然您可以使用 Target
屬性直接系結至 物件做為 的替代方案 TargetName
,但無法序列化。 不保證 Target
物件可以在 XAML 中正確參考。
TargetName若要讓 屬性能夠運作,目標物件必須具有名稱。 將名稱指派給 FrameworkElement 或 FrameworkContentElement XAML 中的 ,與將名稱指派給 Freezable 物件不同。
Framework 元素是繼承自 類別的 FrameworkElement 類別。 架構元素的範例包括 Window 、 DockPanel 、 Button 和 Rectangle 。 基本上所有的視窗、面板和控制項都是元素。 架構內容元素是繼承自 類別的 FrameworkContentElement 類別。 架構內容專案的範例包括 FlowDocument 和 Paragraph 。 如果您不確定某個型別是架構元素或架構內容元素,請檢查它是否具有 Name 屬性。 如果有,它可能是架構元素或架構內容元素。 為了安全起見,請檢查其型別頁面的<繼承階層>一節。
若要在 XAML 中啟用架構專案或架構內容專案的目標,請設定其 Name 屬性。 在程式碼中,您也需要使用 RegisterName 方法來向您已建立 NameScope 的 元素註冊專案名稱。
下列範例取自上述範例,會指派 名稱 MyRectangle
為 Rectangle 的 型別 FrameworkElement 。
<Rectangle Name="MyRectangle"
Width="100"
Height="100">
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "MyRectangle";
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.RegisterName(myRectangle.Name, myRectangle);
在元素具有名稱後,您就可以為該元素的屬性建立動畫。
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="Width"
From="100" To="200" Duration="0:0:1" />
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation,
new PropertyPath(Rectangle.WidthProperty));
Freezable 類型是繼承自 類別的 Freezable 類別。 的 Freezable 範例包括 SolidColorBrush 、 RotateTransform 和 GradientStop 。
若要在 XAML 中透過動畫啟用 的目標 Freezable ,您可以使用 x:Name 指示詞 來指派名稱。 在程式碼中 RegisterName ,您可以使用 方法來向您已建立 NameScope 的 元素註冊其名稱。
下列範例會將名稱指派給 Freezable 物件。
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
然後物件可以作為動畫的目標。
<ColorAnimation
Storyboard.TargetName="MySolidColorBrush"
Storyboard.TargetProperty="Color"
From="Blue" To="Red" Duration="0:0:1" />
Storyboard.SetTargetName(myColorAnimation, "MySolidColorBrush");
Storyboard.SetTargetProperty(myColorAnimation,
new PropertyPath(SolidColorBrush.ColorProperty));
Storyboard 物件會使用名稱範圍來解析 TargetName 屬性。 如需 WPF 名稱範圍的詳細資訊,請參閱 WPF XAML 名稱範圍。 如果省略 屬性 TargetName ,動畫會以其定義所在的專案為目標,或者,如果樣式為樣式,則為樣式專案。
有時無法將名稱指派給 Freezable 物件。 例如,如果 Freezable 宣告為資源,或用來在樣式中設定屬性值,則無法指定名稱。 因為它沒有名稱,就無法直接做為目標,但可間接做為目標。 以下各節會說明如何使用間接目標。
間接目標
動畫 Freezable 有時無法直接以 為目標,例如當 宣告為資源或用來設定樣式中的屬性值時 Freezable 。 在這些情況下,即使您無法直接將目標設為目標,您仍然可以以 Freezable 動畫顯示物件。 您不要使用 的名稱 Freezable 來設定 TargetName 屬性,而是將 「所屬」 專案 Freezable 的名稱提供給它。例如, SolidColorBrush 用來設定 Fill 矩形專案的 屬於該矩形。 若要建立筆刷的動畫效果,您可以使用以架構專案或架構內容元素 Freezable 的 屬性鏈結來設定動畫 TargetProperty ,並以 屬性結尾 Freezable 來設定動畫。
<ColorAnimation
Storyboard.TargetName="Rectangle01"
Storyboard.TargetProperty="Fill.Color"
From="Blue" To="AliceBlue" Duration="0:0:1" />
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);
請注意,如果 Freezable 已凍結,則會製作複製品,而該複製品將會以動畫顯示。 發生這種情況時,原始物件的 HasAnimatedProperties 屬性會繼續傳回 false
,因為原始物件實際上不會產生動畫效果。 如需複製的詳細資訊,請參閱 Freezable 物件概觀。
另請注意,當使用間接屬性目標時,可能會以不存在的物件作為目標。 例如,您可能會假設 Background 特定按鈕的 已設定為 SolidColorBrush ,並嘗試以動畫顯示其 Color,而事實上 LinearGradientBrush 是用來設定按鈕的 Background。 在這些情況下,不會擲回例外狀況;動畫無法產生可見效果,因為 LinearGradientBrush 不會對屬性的變更 Color 做出反應。
以下各節會詳細說明間接屬性目標語法。
在 XAML 中以 Freezable 屬性為間接目標
若要以 XAML 中凍結的 屬性為目標,請使用下列語法。
屬性語法 |
---|
ElementPropertyName. FreezablePropertyName |
其中
ElementPropertyName 是 用來設定 的 FrameworkElementFreezable 屬性,以及
FreezablePropertyName 是要產生動畫效果之 的 Freezable 屬性。
下列程式碼示範如何以動畫顯示 ColorSolidColorBrush 用來設定矩形專案 之 Fill 的 動畫。
<Rectangle
Name="Rectangle01"
Height="100"
Width="100"
Fill="{StaticResource MySolidColorBrushResource}">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Rectangle01"
Storyboard.TargetProperty="Fill.Color"
From="Blue" To="AliceBlue" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
有時候您需要以集合或陣列中包含的 Freezable 為目標。
若要以集合中包含的 Freezable 為目標,請使用下列路徑語法。
路徑語法 |
---|
ElementPropertyName.Children[ CollectionIndex]. FreezablePropertyName |
其中 CollectionIndex 是物件在其陣列或集合中的索引。
例如,假設矩形已 TransformGroup 將資源套用至其 屬性,而您想要讓其中 RenderTransform 一個轉換產生動畫效果。
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
下列程式碼示範如何以動畫顯示 Angle 上一個範例中顯示的 屬性 RotateTransform 。
<Rectangle
Name="Rectangle02"
Height="100"
Width="100"
Fill="Blue"
RenderTransform="{StaticResource MyTransformGroupResource}">
<Rectangle.Triggers>
<EventTrigger RoutedEvent="Rectangle.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Rectangle02"
Storyboard.TargetProperty="RenderTransform.Children[1].Angle"
From="0" To="360" Duration="0:0:1" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
在程式碼中以 Freezable 的屬性為間接目標
在程式碼中,您會建立 PropertyPath 物件。 當您建立 PropertyPath 時,您會指定 Path 和 PathParameters 。
若要建立 PathParameters ,您可以建立類型 DependencyProperty 陣列,其中包含相依性屬性識別碼欄位的清單。 第一個識別碼欄位是 用於 的 FrameworkElement 屬性,或是 FrameworkContentElementFreezable 用來設定的 。 下一個識別碼欄位代表要目標的 屬性 Freezable 。 將其視為將 連接到 FreezableFrameworkElement 物件的屬性鏈結。
以下是相依性屬性鏈結的範例,其目標 ColorSolidColorBrush 為 用來設定 Fill 矩形專案的 。
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
您也需要指定 Path 。 Path是 String ,會告知 Path 如何解譯其 PathParameters 。 它會使用下列語法。
屬性路徑語法 |
---|
( OwnerPropertyArrayIndex).( FreezablePropertyArrayIndex) |
其中
OwnerPropertyArrayIndex 是陣列的 DependencyProperty 索引,其中包含用來設定 的物件屬性 Freezable 識別碼 FrameworkElement ,以及
FreezablePropertyArrayIndex 是陣列的 DependencyProperty 索引,其中包含要鎖定之屬性的識別碼。
下列範例顯示 PathPathParameters 隨附于上述範例中所定義 之 的 。
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
下列範例會結合上述範例中的程式碼,以動畫顯示 ColorSolidColorBrush 用來設定矩形專案 之 Fill 的 動畫。
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
Rectangle rectangle01 = new Rectangle();
rectangle01.Name = "Rectangle01";
this.RegisterName(rectangle01.Name, rectangle01);
rectangle01.Width = 100;
rectangle01.Height = 100;
rectangle01.Fill =
(SolidColorBrush)this.Resources["MySolidColorBrushResource"];
ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Blue;
myColorAnimation.To = Colors.AliceBlue;
myColorAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myColorAnimation, rectangle01.Name);
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myColorAnimation, myPropertyPath);
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myColorAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle01.Triggers.Add(myMouseEnterTrigger);
有時候您需要以集合或陣列中包含的 Freezable 為目標。 例如,假設矩形已 TransformGroup 將資源套用至其 屬性,而您想要讓其中 RenderTransform 一個轉換產生動畫效果。
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
若要以集合中包含的 為目標 Freezable ,請使用下列路徑語法。
路徑語法 |
---|
( OwnerPropertyArrayIndex).( CollectionChildrenPropertyArrayIndex) [ CollectionIndex].( FreezablePropertyArrayIndex) |
其中 CollectionIndex 是物件在其陣列或集合中的索引。
若要以 Angle 的 屬性 RotateTransform 為目標,在 中的 TransformGroup 第二個轉換,您會使用下列 Path 和 PathParameters 。
DependencyProperty[] propertyChain =
new DependencyProperty[]
{
Rectangle.RenderTransformProperty,
TransformGroup.ChildrenProperty,
RotateTransform.AngleProperty
};
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);
下列範例顯示完整程式碼,以動畫顯示 Angle 內 TransformGroup 所含 的 RotateTransform 。
Rectangle rectangle02 = new Rectangle();
rectangle02.Name = "Rectangle02";
this.RegisterName(rectangle02.Name, rectangle02);
rectangle02.Width = 100;
rectangle02.Height = 100;
rectangle02.Fill = Brushes.Blue;
rectangle02.RenderTransform =
(TransformGroup)this.Resources["MyTransformGroupResource"];
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 0;
myDoubleAnimation.To = 360;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTargetName(myDoubleAnimation, rectangle02.Name);
DependencyProperty[] propertyChain =
new DependencyProperty[]
{
Rectangle.RenderTransformProperty,
TransformGroup.ChildrenProperty,
RotateTransform.AngleProperty
};
string thePath = "(0).(1)[1].(2)";
PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
Storyboard.SetTargetProperty(myDoubleAnimation, myPropertyPath);
Storyboard myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
BeginStoryboard myBeginStoryboard = new BeginStoryboard();
myBeginStoryboard.Storyboard = myStoryboard;
EventTrigger myMouseEnterTrigger = new EventTrigger();
myMouseEnterTrigger.RoutedEvent = Rectangle.MouseEnterEvent;
myMouseEnterTrigger.Actions.Add(myBeginStoryboard);
rectangle02.Triggers.Add(myMouseEnterTrigger);
以 Freezable 作為起點的間接目標
前幾節說明如何從 或 開始 FrameworkElement ,以及建立子屬性的屬性鏈結, Freezable 間接鎖定 Freezable 。 FrameworkContentElement 您也可以使用 Freezable 作為起點,並間接鎖定其 Freezable 其中一個子屬性。 當使用 Freezable 做為間接目標的起點時,會套用一個額外的限制:它與間接目標子屬性之間的開始 Freezable 和每 Freezable 一個都不得凍結。
在 XAML 中以互動方式控制分鏡腳本
若要在 Extensible Application Markup Language (XAML) 中啟動分鏡腳本,請使用 BeginStoryboard 觸發程式動作。 BeginStoryboard 將動畫散發至其動畫的物件和屬性,並啟動分鏡腳本。 (如需此程式的詳細資訊,請參閱 動畫和計時系統概觀 。)如果您藉由指定其 Name 屬性來指定 BeginStoryboard 名稱,您可以將它設為可控制的分鏡腳本。 接著在分鏡腳本啟動後,您就可能以互動方式控制它。 以下是可控制之分鏡腳本動作的清單,您可以將這些動作與事件觸發程序搭配使用以控制分鏡腳本。
PauseStoryboard:暫停分鏡腳本。
ResumeStoryboard:繼續暫停的分鏡腳本。
SetStoryboardSpeedRatio:變更分鏡腳本的速度。
SkipStoryboardToFill:如果腳本有一個,則會將分鏡腳本推進到其填滿期間結尾。
StopStoryboard:停止分鏡腳本。
RemoveStoryboard:移除分鏡腳本。
在下列範例中,會使用可控制的分鏡腳本動作以互動方式控制分鏡腳本。
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Microsoft.SDK.Animation.ControllableStoryboardExample"
WindowTitle="Fading Rectangle Example">
<StackPanel Margin="10">
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
</Rectangle>
<Button Name="BeginButton">Begin</Button>
<Button Name="PauseButton">Pause</Button>
<Button Name="ResumeButton">Resume</Button>
<Button Name="SkipToFillButton">Skip To Fill</Button>
<Button Name="StopButton">Stop</Button>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="BeginButton">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyRectangle"
Storyboard.TargetProperty="(Rectangle.Opacity)"
From="1.0" To="0.0" Duration="0:0:5" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="PauseButton">
<PauseStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="ResumeButton">
<ResumeStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="SkipToFillButton">
<SkipStoryboardToFill BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="StopButton">
<StopStoryboard BeginStoryboardName="MyBeginStoryboard" />
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
</Page>
使用程式碼以互動方式控制分鏡腳本
前述範例顯示如何使用觸發動作顯示動畫。 在程式碼中,您也可以使用 類別的 Storyboard 互動式方法來控制分鏡腳本。 Storyboard若要在程式碼中建立互動式的 ,您必須使用腳本方法的適當多載 Begin ,並指定 true
使其可控制。 如需詳細資訊, Begin(FrameworkElement, Boolean) 請參閱頁面。
下列清單顯示可在啟動之後用來操作 Storyboard 的方法:
使用這些方法的優點是,您不需要建立 Trigger 或 TriggerAction 物件;只需要參考您想要操作的可控制物件 Storyboard 。
注意
在 上 Clock 採取的所有互動式動作,因此也會在 計時引擎的下一個刻度上 Storyboard 發生,而該時間引擎將在下一個轉譯前不久發生。 例如,如果您使用 Seek 方法跳至動畫中的另一個點,屬性值不會立即變更,而是在計時引擎的下一個刻度變更值。
下列範例示範如何使用 類別的 Storyboard 互動式方法來套用及控制動畫。
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace SDKSample
{
public class ControllableStoryboardExample : Page
{
private Storyboard myStoryboard;
public ControllableStoryboardExample()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.WindowTitle = "Controllable Storyboard Example";
StackPanel myStackPanel = new StackPanel();
myStackPanel.Margin = new Thickness(10);
// Create a rectangle.
Rectangle myRectangle = new Rectangle();
myRectangle.Name = "myRectangle";
// Assign the rectangle a name by
// registering it with the page, so that
// it can be targeted by storyboard
// animations.
this.RegisterName(myRectangle.Name, myRectangle);
myRectangle.Width = 100;
myRectangle.Height = 100;
myRectangle.Fill = Brushes.Blue;
myStackPanel.Children.Add(myRectangle);
//
// Create an animation and a storyboard to animate the
// rectangle.
//
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 1.0;
myDoubleAnimation.To = 0.0;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(5000));
myDoubleAnimation.AutoReverse = true;
// Create the storyboard.
myStoryboard = new Storyboard();
myStoryboard.Children.Add(myDoubleAnimation);
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Rectangle.OpacityProperty));
//
// Create some buttons to control the storyboard
// and a panel to contain them.
//
StackPanel buttonPanel = new StackPanel();
buttonPanel.Orientation = Orientation.Horizontal;
Button beginButton = new Button();
beginButton.Content = "Begin";
beginButton.Click += new RoutedEventHandler(beginButton_Clicked);
buttonPanel.Children.Add(beginButton);
Button pauseButton = new Button();
pauseButton.Content = "Pause";
pauseButton.Click += new RoutedEventHandler(pauseButton_Clicked);
buttonPanel.Children.Add(pauseButton);
Button resumeButton = new Button();
resumeButton.Content = "Resume";
resumeButton.Click += new RoutedEventHandler(resumeButton_Clicked);
buttonPanel.Children.Add(resumeButton);
Button skipToFillButton = new Button();
skipToFillButton.Content = "Skip to Fill";
skipToFillButton.Click += new RoutedEventHandler(skipToFillButton_Clicked);
buttonPanel.Children.Add(skipToFillButton);
Button setSpeedRatioButton = new Button();
setSpeedRatioButton.Content = "Triple Speed";
setSpeedRatioButton.Click += new RoutedEventHandler(setSpeedRatioButton_Clicked);
buttonPanel.Children.Add(setSpeedRatioButton);
Button stopButton = new Button();
stopButton.Content = "Stop";
stopButton.Click += new RoutedEventHandler(stopButton_Clicked);
buttonPanel.Children.Add(stopButton);
myStackPanel.Children.Add(buttonPanel);
this.Content = myStackPanel;
}
// Begins the storyboard.
private void beginButton_Clicked(object sender, RoutedEventArgs args)
{
// Specifying "true" as the second Begin parameter
// makes this storyboard controllable.
myStoryboard.Begin(this, true);
}
// Pauses the storyboard.
private void pauseButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Pause(this);
}
// Resumes the storyboard.
private void resumeButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Resume(this);
}
// Advances the storyboard to its fill period.
private void skipToFillButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.SkipToFill(this);
}
// Updates the storyboard's speed.
private void setSpeedRatioButton_Clicked(object sender, RoutedEventArgs args)
{
// Makes the storyboard progress three times as fast as normal.
myStoryboard.SetSpeedRatio(this, 3);
}
// Stops the storyboard.
private void stopButton_Clicked(object sender, RoutedEventArgs args)
{
myStoryboard.Stop(this);
}
}
}
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Shapes
Imports System.Windows.Media
Imports System.Windows.Media.Animation
Namespace SDKSample
Public Class ControllableStoryboardExample
Inherits Page
Private myStoryboard As Storyboard
Public Sub New()
' Create a name scope for the page.
NameScope.SetNameScope(Me, New NameScope())
Me.WindowTitle = "Controllable Storyboard Example"
Dim myStackPanel As New StackPanel()
myStackPanel.Margin = New Thickness(10)
' Create a rectangle.
Dim myRectangle As New Rectangle()
myRectangle.Name = "myRectangle"
' Assign the rectangle a name by
' registering it with the page, so that
' it can be targeted by storyboard
' animations.
Me.RegisterName(myRectangle.Name, myRectangle)
myRectangle.Width = 100
myRectangle.Height = 100
myRectangle.Fill = Brushes.Blue
myStackPanel.Children.Add(myRectangle)
'
' Create an animation and a storyboard to animate the
' rectangle.
'
Dim myDoubleAnimation As New DoubleAnimation()
myDoubleAnimation.From = 1.0
myDoubleAnimation.To = 0.0
myDoubleAnimation.Duration = New Duration(TimeSpan.FromMilliseconds(5000))
myDoubleAnimation.AutoReverse = True
' Create the storyboard.
myStoryboard = New Storyboard()
myStoryboard.Children.Add(myDoubleAnimation)
Storyboard.SetTargetName(myDoubleAnimation, myRectangle.Name)
Storyboard.SetTargetProperty(myDoubleAnimation, New PropertyPath(Rectangle.OpacityProperty))
'
' Create some buttons to control the storyboard
' and a panel to contain them.
'
Dim buttonPanel As New StackPanel()
buttonPanel.Orientation = Orientation.Horizontal
Dim beginButton As New Button()
beginButton.Content = "Begin"
AddHandler beginButton.Click, AddressOf beginButton_Clicked
buttonPanel.Children.Add(beginButton)
Dim pauseButton As New Button()
pauseButton.Content = "Pause"
AddHandler pauseButton.Click, AddressOf pauseButton_Clicked
buttonPanel.Children.Add(pauseButton)
Dim resumeButton As New Button()
resumeButton.Content = "Resume"
AddHandler resumeButton.Click, AddressOf resumeButton_Clicked
buttonPanel.Children.Add(resumeButton)
Dim skipToFillButton As New Button()
skipToFillButton.Content = "Skip to Fill"
AddHandler skipToFillButton.Click, AddressOf skipToFillButton_Clicked
buttonPanel.Children.Add(skipToFillButton)
Dim setSpeedRatioButton As New Button()
setSpeedRatioButton.Content = "Triple Speed"
AddHandler setSpeedRatioButton.Click, AddressOf setSpeedRatioButton_Clicked
buttonPanel.Children.Add(setSpeedRatioButton)
Dim stopButton As New Button()
stopButton.Content = "Stop"
AddHandler stopButton.Click, AddressOf stopButton_Clicked
buttonPanel.Children.Add(stopButton)
myStackPanel.Children.Add(buttonPanel)
Me.Content = myStackPanel
End Sub
' Begins the storyboard.
Private Sub beginButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
' Specifying "true" as the second Begin parameter
' makes this storyboard controllable.
myStoryboard.Begin(Me, True)
End Sub
' Pauses the storyboard.
Private Sub pauseButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.Pause(Me)
End Sub
' Resumes the storyboard.
Private Sub resumeButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.Resume(Me)
End Sub
' Advances the storyboard to its fill period.
Private Sub skipToFillButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.SkipToFill(Me)
End Sub
' Updates the storyboard's speed.
Private Sub setSpeedRatioButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
' Makes the storyboard progress three times as fast as normal.
myStoryboard.SetSpeedRatio(Me, 3)
End Sub
' Stops the storyboard.
Private Sub stopButton_Clicked(ByVal sender As Object, ByVal args As RoutedEventArgs)
myStoryboard.Stop(Me)
End Sub
End Class
End Namespace
在樣式中建立動畫
您可以使用 Storyboard 物件在 中 Style 定義動畫。 使用 Storyboard 中的 Style 動畫類似于使用其他地方,但有下列三個 Storyboard 例外狀況:
您未指定 TargetName ;一 Storyboard 律會將 套用 的專案 Style 設為目標。 若要以物件為目標 Freezable ,您必須使用間接目標。 如需間接目標的詳細資訊,請參閱 間接目標一節。
您無法為 EventTrigger 或 Trigger 指定 SourceName 。
您無法使用動態資源參考或資料系結運算式來設定 Storyboard 或動畫屬性值。 這是因為 內 Style 的所有專案都必須是安全線程,而計時系統必須 FreezeStoryboard 有 物件,才能讓它們安全線程。 Storyboard如果它或其子時間軸包含動態資源參考或資料系結運算式,則無法凍結 。 如需凍結和其他 Freezable 功能的詳細資訊,請參閱 Freezable 物件概觀 。
在 XAML 中,您無法宣告 或 動畫事件的事件處理常式 Storyboard 。
如需如何在樣式中定義分鏡腳本的範例,請參閱 在樣式中建立動畫範例。
在 ControlTemplate 中建立動畫
您可以使用 Storyboard 物件在 中 ControlTemplate 定義動畫。 Storyboard使用 中的 ControlTemplate 動畫類似于使用其他地方,但有下列兩個 Storyboard 例外狀況:
TargetName只能參考 的 ControlTemplate 子物件。 如果未 TargetName 指定 ,動畫會以 套用 的專案 ControlTemplate 為目標。
SourceNameEventTrigger 或 Trigger 的 只能參考 的 ControlTemplate 子物件。
您無法使用動態資源參考或資料系結運算式來設定 Storyboard 或動畫屬性值。 這是因為 內 ControlTemplate 的所有專案都必須是安全線程,而計時系統必須 FreezeStoryboard 有 物件,才能讓它們安全線程。 Storyboard如果它或其子時間軸包含動態資源參考或資料系結運算式,則無法凍結 。 如需凍結和其他 Freezable 功能的詳細資訊,請參閱 Freezable 物件概觀 。
在 XAML 中,您無法宣告 或 動畫事件的事件處理常式 Storyboard 。
如需示範如何在 中 ControlTemplate 定義分鏡腳本的範例,請參閱 ControlTemplate 範例中的 Animate。
在屬性值變更時建立動畫
在樣式和控制項範本中,您可以使用 Trigger 物件在屬性變更時啟動分鏡腳本。 如需範例,請參閱在屬性值變更時觸發動畫和 在 ControlTemplate 中建立動畫。
屬性 Trigger 物件所套用的動畫行為比 EventTrigger 使用 Storyboard 方法開始的動畫或動畫更為複雜。 它們會以其他 Trigger 物件定義的動畫「交接」,但會使用 EventTrigger 和 方法觸發的動畫來撰寫。
另請參閱
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應