共用方式為


分鏡腳本概觀

本主題說明如何使用 Storyboard 物件 (部分機器翻譯) 來組織和套用動畫。 其描述如何以互動方式操作 Storyboard 物件 (部分機器翻譯),並描述間接屬性目標語法。

必要條件

若要了解本主題,您應該熟悉不同的動畫類型及其基本功能。 如需動畫的簡介,請參閱動畫概觀。 您也應該了解如何使用附加屬性。 如需附加屬性的詳細資訊,請參閱附加屬性概觀

什麼是分鏡腳本

動畫不是唯一有用的時間軸型別。 還有其他時間軸類別可以協助您組織時間軸集合,以及將時間軸套用至屬性。 容器時間軸衍生自 TimelineGroup 類別 (部分機器翻譯),並包括 ParallelTimeline (部分機器翻譯) 和 Storyboard (部分機器翻譯)。

Storyboard (部分機器翻譯) 是一種容器時間軸類型,可為其所包括的時間軸提供目標資訊。 分鏡腳本可以包含任何類型的 Timeline (部分機器翻譯),包括其他容器時間軸和動畫。 Storyboard 物件 (部分機器翻譯) 可讓您將影響各種物件和屬性的時間軸組合成單一時間軸樹狀結構,以輕鬆地組織和控制複雜的計時行為。 例如,假設您想讓按鈕執行下列三個動作。

  • 在使用者選取按鈕時放大及變更色彩。

  • 按一下按鈕時縮小再放大回原本大小。

  • 在停用時縮小並淡化到 50% 的不透明度。

在此案例中,您有多組套用至同一個物件的動畫,並且想要視按鈕的狀態在不同時間播放。 Storyboard 物件 (部分機器翻譯) 可讓您組織動畫,並將其以群組的形式套用至一或多個物件。

何處可以使用分鏡腳本

您可以使用 Storyboard (部分機器翻譯) 以可展示動畫之類別的相依屬性來建立動畫 (如需類別如何為類別建立動畫的詳細資訊,請參閱動畫概觀 (部分機器翻譯))。 不過,由於分鏡腳本是架構層級的功能,因此物件必須屬於 FrameworkElement (部分機器翻譯) 或 FrameworkContentElement (部分機器翻譯) 的 NameScope (部分機器翻譯)。

例如,您可以使用 Storyboard (部分機器翻譯) 來執行下列動作:

不過,您無法使用 Storyboard (部分機器翻譯) 以動畫顯示未使用 FrameworkElement (部分機器翻譯) 或 FrameworkContentElement (部分機器翻譯) 註冊其名稱,或未用來設定 FrameworkElement (部分機器翻譯) 或 FrameworkContentElement (部分機器翻譯) 的屬性的 SolidColorBrush (部分機器翻譯)。

如何以分鏡腳本套用動畫

若要使用 Storyboard (部分機器翻譯) 來組織和套用動畫,您會將動畫新增為 Storyboard (部分機器翻譯) 的子時間軸。 Storyboard (部分機器翻譯) 類別提供 Storyboard.TargetName (英文) 和 Storyboard.TargetProperty (英文) 附加屬性。 您可以設定動畫的這些屬性以指定其目標物件和屬性。

若要將動畫套用至其目標,您會使用觸發程序動作或方法來開始進行 Storyboard (部分機器翻譯)。 在 XAML 中,您會使用 BeginStoryboard 物件 (部分機器翻譯) 搭配 EventTrigger (部分機器翻譯)、Trigger (部分機器翻譯) 或 DataTrigger (英文)。 在程式碼中,您也可以使用 Begin 方法 (部分機器翻譯)。

下表顯示支援每種 Storyboard (部分機器翻譯) 開始技術的不同位置:每個執行個體、樣式、控制項範本,以及資料範本。 「每個執行個體」指的是將動畫或分鏡腳本直接套用至物件之執行個體,而非樣式、控制項範本或資料範本的技術。

開始分鏡腳本的方法… 每個執行個體 樣式 控制項範本 DataTemplate \(英文\) 範例
BeginStoryboard (部分機器翻譯) 和 EventTrigger (部分機器翻譯) Yes .是 .是 Yes 使用分鏡腳本建立屬性的動畫
BeginStoryboard (部分機器翻譯) 和 Trigger (部分機器翻譯) 屬性 No .是 .是 Yes 在屬性值變更時觸發動畫
BeginStoryboard (部分機器翻譯) 和 MultiTrigger (部分機器翻譯) 屬性 No .是 .是 Yes MultiTrigger 類別範例 (部分機器翻譯)
BeginStoryboard (部分機器翻譯) 和 DataTrigger (部分機器翻譯) No .是 .是 Yes 操作說明︰在資料變更時觸發動畫
BeginStoryboard (部分機器翻譯) 和 MultiDataTrigger (部分機器翻譯) No .是 .是 Yes MultiDataTrigger 類別範例 (英文)
Begin 方法 No 使用分鏡腳本建立屬性的動畫

下列範例會使用 Storyboard (部分機器翻譯),以動畫顯示 Rectangle 元素 (部分機器翻譯) 的 Width (部分機器翻譯) 和用來繪製該 Rectangle (部分機器翻譯) 之 SolidColorBrush (部分機器翻譯) 的 Color (英文)。

<!-- 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 (英文) 屬性,來指定您想要以動畫顯示之屬性的物件名稱。

警告

雖然作為 TargetName 的替代方案,您可以使用 Target 屬性來直接繫結至物件,但其並非可序列化。 不保證可以在 XAML 中正確參考 Target 物件。

若要讓 TargetName 屬性 (英文) 運作,目標對象必須具有名稱。 將名稱指派給 XAML 中的 FrameworkElement (部分機器翻譯) 或 FrameworkContentElement (部分機器翻譯),與將名稱指派給 Freezable 物件 (部分機器翻譯) 不同。

架構元素是繼承自 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 (部分機器翻譯)「所屬」的元素名稱。例如,用來設定矩形元素之 Fill (英文) 的 SolidColorBrush (部分機器翻譯),是屬於該矩形的。 若要以動畫顯示筆刷,您會使用一連串的屬性來設定動畫的 TargetProperty (英文),其會從使用 Freezable (部分機器翻譯) 來設定的架構元素或架構內容元素的屬性開始,並以要以動畫顯示的 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 中以 Freezable 屬性為目標,請使用下列語法。

屬性語法
ElementPropertyName . FreezablePropertyName

其中

  • ElementPropertyName 是使用 Freezable (部分機器翻譯) 來設定之 FrameworkElement (部分機器翻譯) 的屬性,而且

  • FreezablePropertyName 是要以動畫顯示之 Freezable (部分機器翻譯) 的屬性。

下列程式碼示範如何以動畫顯示用來設定矩形元素之 Fill (英文) 的 SolidColorBrush (部分機器翻譯) 的 Color (部分機器翻譯)。

<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>

下列程式碼示範如何以動畫顯示上一個範例中顯示之 RotateTransform (部分機器翻譯) 的 Angle 屬性 (部分機器翻譯)。

<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 (部分機器翻譯) 的陣列,其中包含相依性屬性識別碼欄位的清單。 第一個識別碼欄位是用於使用 Freezable (部分機器翻譯) 來設定的 FrameworkElement (部分機器翻譯) 或 FrameworkContentElement (部分機器翻譯) 的屬性。 下一個識別碼欄位代表要作為目標之 Freezable (部分機器翻譯) 的屬性。 將其視為將 Freezable (部分機器翻譯) 連接到 FrameworkElement 物件 (部分機器翻譯) 的一連串屬性。

以下是相依性屬性鏈結的範例,其以用來設定矩形元素之 Color (英文) 的 SolidColorBrush (部分機器翻譯) 的 Fill (部分機器翻譯) 作為目標。

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};

您也需要指定 Path (英文)。 Path (英文) 是會告訴 Path (英文) 如何解譯其 PathParameters (部分機器翻譯) 的 String (部分機器翻譯)。 它會使用下列語法。

屬性路徑語法
( OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex )

其中

  • OwnerPropertyArrayIndexDependencyProperty (部分機器翻譯) 陣列的索引,其中包含使用 FrameworkElement (部分機器翻譯) 來設定之 Freezable 物件 (部分機器翻譯) 屬性的識別碼,而且

  • FreezablePropertyArrayIndex 是包含要作為目標的屬性識別碼之 DependencyProperty 陣列 (部分機器翻譯) 的索引。

下列範例顯示會隨附於在上一個範例中定義之 PathParametersPath

DependencyProperty[] propertyChain =
    new DependencyProperty[]
        {Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";

下列範例會結合上述範例中的程式碼,以動畫顯示用來設定矩形元素之 Fill (部分機器翻譯) 的 SolidColorBrush (部分機器翻譯) 的 Color (英文)。


// 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 是物件在其陣列或集合中的索引。

若要以 TransformGroup (部分機器翻譯) 中的第二個轉換,RotateTransform (部分機器翻譯) 的 Angle 屬性 (部分機器翻譯) 為目標,您會使用下列 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);

下列範例顯示以動畫顯示包含在 TransformGroup (部分機器翻譯) 內之 RotateTransform (部分機器翻譯) 的 Angle (部分機器翻譯) 的完整程式碼。

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 (部分機器翻譯) 或 FrameworkContentElement (部分機器翻譯) 開始,並建立針對 Freezable 子屬性 (部分機器翻譯) 的屬性鏈結,來間接以 Freezable (部分機器翻譯) 作為目標。 您也可以使用 Freezable 作為起點,並間接以其中一個 Freezable 子屬性 (部分機器翻譯) 作為目標。 使用 Freezable (部分機器翻譯) 作為間接目標的起點時,適用一個額外的限制:作為開始的 Freezable (部分機器翻譯),以及其與間接目標子屬性之間的每個 Freezable (部分機器翻譯) 都不得凍結。

在 XAML 中以互動方式控制分鏡腳本

若要在 Extensible Application Markup Language (XAML) 中啟動分鏡腳本,請使用 BeginStoryboard 觸發程序動作 (部分機器翻譯)。 BeginStoryboard (部分機器翻譯) 會將動畫散發至其以動畫顯示的物件和屬性,然後啟動分鏡腳本。 (如需此流程的詳細資料,請參閱動畫和計時系統概觀 (部分機器翻譯)。)如果您藉由指定 BeginStoryboard (部分機器翻譯) 的 Name 屬性 (部分機器翻譯) 來指定其名稱,您會使其成為可控制的分鏡腳本。 接著在分鏡腳本啟動後,您就可能以互動方式控制它。 以下是可控制之分鏡腳本動作的清單,您可以將這些動作與事件觸發程序搭配使用以控制分鏡腳本。

在下列範例中,會使用可控制的分鏡腳本動作以互動方式控制分鏡腳本。

<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 (部分機器翻譯) 中定義動畫。 使用 Style (部分機器翻譯) 中的 Storyboard (部分機器翻譯) 顯示動畫,類似於在其他地方使用 Storyboard (部分機器翻譯) 來顯示動畫,但有下列三個例外:

  • 您未指定 TargetName (英文);Storyboard (部分機器翻譯) 一律以套用 Style (部分機器翻譯) 的元素為目標。 若要以 Freezable 物件 (部分機器翻譯) 為目標,您必須使用間接目標。 如需間接目標的詳細資訊,請參閱 間接目標一節。

  • 您無法為 EventTrigger (部分機器翻譯) 或 Trigger (部分機器翻譯) 指定 SourceName (英文)。

  • 您無法使用動態資源參考或資料繫結運算式來設定 Storyboard (部分機器翻譯) 或動畫屬性值。 這是因為 Style (部分機器翻譯) 內的所有項目都必須是安全執行緒,而計時系統必須對物件進行 Freeze (部分機器翻譯) Storyboard (部分機器翻譯),才能使其成為安全執行緒。 如果 Storyboard (部分機器翻譯) 或其子時間軸包含動態資源參考或資料繫結運算式,則其無法凍結。 如需凍結和其他 Freezable (部分機器翻譯) 功能的詳細資訊,請參閱 Freezable 物件概觀 (部分機器翻譯)。

  • 在 XAML 中,您無法宣告 Storyboard (部分機器翻譯) 或動畫事件的事件處理常式。

如需如何在樣式中定義分鏡腳本的範例,請參閱 在樣式中建立動畫範例。

在 ControlTemplate 中建立動畫

您可以使用 Storyboard 物件 (部分機器翻譯),在 ControlTemplate (部分機器翻譯) 中定義動畫。 使用 ControlTemplate (部分機器翻譯) 中的 Storyboard (部分機器翻譯) 顯示動畫,類似於在其他地方使用 Storyboard (部分機器翻譯) 來顯示動畫,但有下列兩個例外:

  • TargetName (部分機器翻譯) 只能參考 ControlTemplate (部分機器翻譯) 的子物件。 如果未指定 TargetName (英文),動畫會以套用 ControlTemplate (部分機器翻譯) 的元素為目標。

  • EventTrigger (部分機器翻譯) 或 Trigger (部分機器翻譯) 的 SourceName (部分機器翻譯) 只能參考 ControlTemplate (部分機器翻譯) 的子物件。

  • 您無法使用動態資源參考或資料繫結運算式來設定 Storyboard (部分機器翻譯) 或動畫屬性值。 這是因為 ControlTemplate (部分機器翻譯) 內的所有項目都必須是安全執行緒,而計時系統必須對物件進行 Freeze (部分機器翻譯) Storyboard (部分機器翻譯),才能使其成為安全執行緒。 如果 Storyboard (部分機器翻譯) 或其子時間軸包含動態資源參考或資料繫結運算式,則其無法凍結。 如需凍結和其他 Freezable (部分機器翻譯) 功能的詳細資訊,請參閱 Freezable 物件概觀 (部分機器翻譯)。

  • 在 XAML 中,您無法宣告 Storyboard (部分機器翻譯) 或動畫事件的事件處理常式。

如需如何在 ControlTemplate (部分機器翻譯) 中定義分鏡腳本的範例,請參閱在 ControlTemplate 中建立動畫 範例 (部分機器翻譯)。

在屬性值變更時建立動畫

在樣式和控制項範本中,您可以使用 Trigger 物件在屬性變更時啟動分鏡腳本。 如需範例,請參閱在屬性值變更時觸發動畫在 ControlTemplate 中建立動畫

由屬性 Trigger 物件 (部分機器翻譯) 套用的動畫行為比起 EventTrigger (部分機器翻譯) 動畫或使用 Storyboard (部分機器翻譯) 方法開始的動畫更為複雜。 其會「交接」由其他 Trigger 物件 (部分機器翻譯) 定義的動畫,但其中包含 EventTrigger (部分機器翻譯) 和由方法觸發的動畫。

另請參閱