Bagikan melalui


Gambaran Umum Papan Cerita

Topik ini memperlihatkan cara menggunakan Storyboard objek untuk menata dan menerapkan animasi. Ini menjelaskan cara memanipulasi Storyboard objek secara interaktif dan menjelaskan sintaks penargetan properti tidak langsung.

Prasyarat

Untuk memahami topik ini, Anda harus terbiasa dengan berbagai jenis animasi dan fitur dasarnya. Untuk pengenalan animasi, lihat Gambaran Umum Animasi. Anda juga harus tahu cara menggunakan properti terlampir. Untuk informasi selengkapnya tentang properti terlampir, lihat Gambaran Umum Properti Terlampir.

Apa itu Storyboard

Animasi bukan satu-satunya jenis garis waktu yang berguna. Kelas garis waktu lainnya disediakan untuk membantu Anda mengatur serangkaian garis waktu, dan untuk menerapkan garis waktu ke properti. Garis waktu kontainer berasal dari TimelineGroup kelas , dan sertakan ParallelTimeline dan Storyboard.

Storyboard adalah jenis garis waktu kontainer yang menyediakan informasi penargetan untuk garis waktu yang dikandungnya. Papan Cerita dapat berisi semua jenis Timeline, termasuk garis waktu dan animasi kontainer lainnya. Storyboard Objek memungkinkan Anda menggabungkan garis waktu yang memengaruhi berbagai objek dan properti ke dalam satu pohon garis waktu, sehingga mudah untuk mengatur dan mengontrol perilaku pengaturan waktu yang kompleks. Misalnya, Anda menginginkan tombol yang melakukan tiga hal ini.

  • Tumbuh dan ubah warna saat pengguna memilih tombol .

  • Susutkan dan kemudian tumbuh kembali ke ukuran aslinya saat diklik.

  • Menyusutkan dan memudar menjadi 50 persen opasitas ketika menjadi dinonaktifkan.

Dalam hal ini, Anda memiliki beberapa set animasi yang berlaku untuk objek yang sama, dan Anda ingin bermain pada waktu yang berbeda, tergantung pada status tombol. Storyboard objek memungkinkan Anda menata animasi dan menerapkannya dalam grup ke satu atau beberapa objek.

Di mana Anda Dapat Menggunakan Storyboard

Storyboard Dapat digunakan untuk menganimasikan properti dependensi kelas yang dapat dianimasikan (untuk informasi selengkapnya tentang apa yang membuat kelas dapat dianimasikan, lihat Gambaran Umum Animasi). Namun, karena storyboarding adalah fitur tingkat kerangka kerja, objek harus milik NameScope dari FrameworkElement atau FrameworkContentElement.

Misalnya, Anda dapat menggunakan Storyboard untuk melakukan hal berikut:

Namun, Anda tidak dapat menggunakan Storyboard untuk menganimasikan SolidColorBrush yang tidak mendaftarkan namanya dengan FrameworkElement atau FrameworkContentElement, atau tidak digunakan untuk mengatur properti dari FrameworkElement atau FrameworkContentElement.

Cara Menerapkan Animasi dengan Papan Cerita

Untuk menggunakan Storyboard untuk mengatur dan menerapkan animasi, Anda menambahkan animasi sebagai garis waktu turunan dari Storyboard. Kelas Storyboard menyediakan properti yang Storyboard.TargetName terlampir dan Storyboard.TargetProperty . Anda mengatur properti ini pada animasi untuk menentukan objek dan properti targetnya.

Untuk menerapkan animasi ke targetnya, Anda memulai Storyboard menggunakan tindakan pemicu atau metode. Di XAML, Anda menggunakan BeginStoryboard objek dengan EventTrigger, , Triggeratau DataTrigger. Dalam kode, Anda juga dapat menggunakan metode .Begin

Tabel berikut menunjukkan berbagai tempat di mana setiap Storyboard teknik pemula didukung: per instans, gaya, templat kontrol, dan templat data. "Per Instans" mengacu pada teknik menerapkan animasi atau papan cerita langsung ke instans objek, bukan dalam gaya, templat kontrol, atau templat data.

Papan cerita dimulai menggunakan... Per instans Gaya Templat kontrol Templat data Contoh
BeginStoryboard dan EventTrigger Ya Ya Ya Ya Menganimasikan Properti dengan Menggunakan Storyboard
BeginStoryboard dan properti Trigger Tidak Ya Ya Ya Memicu Animasi Saat Nilai Properti Berubah
BeginStoryboard dan properti MultiTrigger Tidak Ya Ya Ya Contoh kelas MultiTrigger
BeginStoryboard dan a DataTrigger Tidak Ya Ya Ya Cara: Memicu Animasi Saat Data Berubah
BeginStoryboard dan a MultiDataTrigger Tidak Ya Ya Ya Contoh kelas MultiDataTrigger
metode Begin Ya No No Tidak Menganimasikan Properti dengan Menggunakan Storyboard

Contoh berikut menggunakan Storyboard untuk menganimasikan Rectangle Width elemen dan Color dari yang SolidColorBrush digunakan untuk melukis itu 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;
        }
    }
}

Bagian berikut ini menjelaskan TargetName dan TargetProperty melampirkan properti secara lebih rinci.

Menargetkan Elemen Kerangka Kerja, Elemen Konten Kerangka Kerja, dan Freezables

Bagian sebelumnya menyebutkan bahwa, agar animasi menemukan targetnya, harus mengetahui nama target dan properti untuk dianimasikan. Menentukan properti untuk dianimasikan lurus ke depan: cukup atur TargetProperty dengan nama properti untuk dianimasikan. Anda menentukan nama objek yang propertinya ingin Anda animasikan dengan mengatur Storyboard.TargetName properti pada animasi.

Perhatian

Meskipun Anda dapat menggunakan Target properti untuk mengikat langsung ke objek sebagai alternatif untuk TargetName, properti tidak dapat diserialisasikan. Tidak ada jaminan bahwa Target objek dapat direferensikan dengan benar di XAML.

TargetName Agar properti berfungsi, objek yang ditargetkan harus memiliki nama. Menetapkan nama ke FrameworkElement atau FrameworkContentElement di XAML berbeda dari menetapkan nama ke Freezable objek.

Elemen kerangka kerja adalah kelas yang mewarisi dari FrameworkElement kelas . Contoh elemen kerangka kerja termasuk Window, , DockPanel, Buttondan Rectangle. Pada dasarnya semua jendela, panel, dan kontrol adalah elemen. Elemen konten kerangka kerja adalah kelas yang mewarisi dari FrameworkContentElement kelas . Contoh elemen konten kerangka kerja meliputi FlowDocument dan Paragraph. Jika Anda tidak yakin apakah jenis adalah elemen kerangka kerja atau elemen konten kerangka kerja, periksa untuk melihat apakah jenis tersebut memiliki properti Nama. Jika ya, mungkin elemen kerangka kerja atau elemen konten kerangka kerja. Untuk memastikannya, periksa bagian Hierarki Warisan dari halaman jenisnya.

Untuk mengaktifkan penargetan elemen kerangka kerja atau elemen konten kerangka kerja di XAML, Anda mengatur propertinya Name . Dalam kode, Anda juga perlu menggunakan RegisterName metode untuk mendaftarkan nama elemen dengan elemen tempat Anda membuat NameScope.

Contoh berikut, yang diambil dari contoh sebelumnya, menetapkan nama MyRectangle , Rectanglejenis 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);

Setelah memiliki nama, Anda dapat menganimasikan properti elemen tersebut.

<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 jenis adalah kelas yang mewarisi dari Freezable kelas . Freezable Contohnya termasuk SolidColorBrush, RotateTransform, dan GradientStop.

Untuk mengaktifkan penargetan dengan Freezable animasi di XAML, Anda menggunakan x:Name Directive untuk menetapkan nama. Dalam kode, Anda menggunakan RegisterName metode untuk mendaftarkan namanya dengan elemen yang telah Anda buat NameScope.

Contoh berikut menetapkan nama ke Freezable objek.

<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);

Objek kemudian dapat ditargetkan oleh animasi.

<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 objek menggunakan cakupan nama untuk menyelesaikan TargetName properti. Untuk informasi selengkapnya tentang cakupan nama WPF, lihat Namescope WPF XAML. Jika properti dihilangkan TargetName , animasi menargetkan elemen tempat properti didefinisikan, atau, dalam kasus gaya, elemen bergaya.

Terkadang nama tidak dapat ditetapkan ke Freezable objek. Misalnya, jika Freezable dideklarasikan sebagai sumber daya atau digunakan untuk menetapkan nilai properti dalam gaya, nilai tidak dapat diberi nama. Karena tidak memiliki nama, nama tidak dapat ditargetkan secara langsung—tetapi dapat ditargetkan secara tidak langsung. Bagian berikut menjelaskan cara menggunakan penargetan tidak langsung.

Penargetan Tidak Langsung

Ada kalanya Freezable tidak dapat ditargetkan langsung oleh animasi, seperti ketika Freezable dideklarasikan sebagai sumber daya atau digunakan untuk mengatur nilai properti dalam gaya. Dalam kasus ini, meskipun Anda tidak dapat menargetkannya secara langsung, Anda masih dapat menganimasikan Freezable objek. Alih-alih mengatur TargetName properti dengan nama Freezable, Anda memberinya nama elemen tempat Freezable "milik." Misalnya, yang SolidColorBrush digunakan untuk mengatur Fill elemen persegi panjang milik persegi panjang tersebut. Untuk menganimasikan kuas, Anda akan mengatur animasi TargetProperty dengan rantai properti yang dimulai di properti elemen kerangka kerja atau elemen Freezable konten kerangka kerja yang digunakan untuk mengatur dan diakhir dengan Freezable properti untuk menganimasikan.

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

Perhatikan bahwa, jika Freezable dibekukan, klon akan dibuat, dan klon tersebut akan dianimasikan. Ketika ini terjadi, properti objek HasAnimatedProperties asli terus mengembalikan false, karena objek asli tidak benar-benar dianimasikan. Untuk informasi selengkapnya tentang kloning, lihat Gambaran Umum Objek yang Dapat Dibekukan.

Perhatikan juga bahwa, saat menggunakan penargetan properti tidak langsung, dimungkinkan untuk menargetkan objek yang tidak ada. Misalnya, Anda mungkin berasumsi bahwa Background tombol tertentu diatur dengan SolidColorBrush dan mencoba menganimasikan Warnanya, padahal sebenarnya digunakan LinearGradientBrush untuk mengatur Latar Belakang tombol. Dalam kasus ini, tidak ada pengecualian yang dilemparkan; animasi gagal memiliki efek yang terlihat karena LinearGradientBrush tidak bereaksi terhadap perubahan pada Color properti.

Bagian berikut ini menjelaskan sintaks penargetan properti tidak langsung secara lebih rinci.

Secara tidak langsung Menargetkan Properti dari Freezable di XAML

Untuk menargetkan properti yang dapat di-freezable di XAML, gunakan sintaks berikut.

Sintaks properti
ElementPropertyName . FreezablePropertyName

Di mana

  • ElementPropertyName adalah properti FrameworkElement tempat Freezable digunakan untuk mengatur, dan

  • FreezablePropertyName adalah properti untuk menganimasikan Freezable .

Kode berikut menunjukkan cara menganimasikan Color dari yang SolidColorBrush digunakan untuk mengatur Fill elemen persegi panjang.

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

Terkadang Anda perlu menargetkan freezable yang terkandung dalam koleksi atau array.

Untuk menargetkan freezable yang terkandung dalam koleksi, Anda menggunakan sintaks jalur berikut.

Sintaksis jalur
ElementPropertyName .Children[ CollectionIndex ]. FreezablePropertyName

Di mana CollectionIndex adalah indeks objek dalam array atau koleksinya.

Misalnya, misalkan persegi panjang memiliki sumber daya yang TransformGroup diterapkan ke propertinya RenderTransform , dan Anda ingin menganimasikan salah satu transformasi yang dikandungnya.

<TransformGroup x:Key="MyTransformGroupResource"
  x:Shared="False">
  <ScaleTransform />
  <RotateTransform />
</TransformGroup>

Kode berikut menunjukkan cara menganimasikan Angle properti dari yang RotateTransform diperlihatkan dalam contoh sebelumnya.

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

Secara tidak langsung Menargetkan Properti dari Freezable dalam Kode

Dalam kode, Anda membuat PropertyPath objek. Saat Anda membuat PropertyPath, Anda menentukan Path dan PathParameters.

Untuk membuat PathParameters, Anda membuat array jenis DependencyProperty yang berisi daftar bidang pengidentifikasi properti dependensi. Bidang pengidentifikasi pertama adalah untuk properti dari FrameworkElement atau FrameworkContentElement yang Freezable digunakan untuk mengatur. Bidang pengidentifikasi berikutnya mewakili properti dari target ke Freezable . Anggap saja sebagai rantai properti yang menghubungkan ke Freezable FrameworkElement objek.

Berikut ini adalah contoh rantai properti dependensi yang menargetkan Color dari yang SolidColorBrush digunakan untuk mengatur Fill elemen persegi panjang.

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

Anda juga perlu menentukan Path. adalah Path yang String memberi tahu Path cara menafsirkan .PathParameters Ini menggunakan sintaks berikut.

Sintaks jalur properti
(OwnerPropertyArrayIndex ).( FreezablePropertyArrayIndex )

Di mana

Contoh berikut menunjukkan Path yang akan menyertai yang PathParameters ditentukan dalam contoh sebelumnya.

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

Contoh berikut menggabungkan kode dalam contoh sebelumnya untuk menganimasikan Color dari yang SolidColorBrush digunakan untuk mengatur Fill elemen persegi panjang.


// 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);

Terkadang Anda perlu menargetkan freezable yang terkandung dalam koleksi atau array. Misalnya, misalkan persegi panjang memiliki sumber daya yang TransformGroup diterapkan ke propertinya RenderTransform , dan Anda ingin menganimasikan salah satu transformasi yang dikandungnya.

<TransformGroup x:Key="MyTransformGroupResource"
  x:Shared="False">
  <ScaleTransform />
  <RotateTransform />
</TransformGroup>  

Untuk menargetkan yang Freezable terkandung dalam koleksi, Anda menggunakan sintaks jalur berikut.

Sintaksis jalur
(OwnerPropertyArrayIndex ).( CollectionChildrenPropertyArrayIndex ) [ CollectionIndex ].( FreezablePropertyArrayIndex )

Di mana CollectionIndex adalah indeks objek dalam array atau koleksinya.

Untuk menargetkan Angle properti , transformasi kedua di TransformGroup, Anda akan menggunakan berikut dan Path PathParametersRotateTransform.

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

Contoh berikut menunjukkan kode lengkap untuk menganimasikan Angle dari yang RotateTransform terkandung dalam TransformGroup.

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

Penargetan Tidak Langsung dengan Freezable sebagai Titik Awal

Bagian sebelumnya menjelaskan cara menargetkan secara Freezable tidak langsung dengan memulai dengan FrameworkElement atau FrameworkContentElement dan membuat rantai properti ke Freezable sub-properti. Anda juga dapat menggunakan Freezable sebagai titik awal dan secara tidak langsung menargetkan salah satu sub-propertinya Freezable . Satu pembatasan tambahan berlaku saat menggunakan Freezable sebagai titik awal untuk penargetan tidak langsung: awal Freezable dan setiap Freezable di antaranya dan sub-properti yang ditargetkan secara tidak langsung tidak boleh dibekukan.

Mengontrol Storyboard secara interaktif di XAML

Untuk memulai papan cerita dalam Extensible Application Markup Language (XAML), Anda menggunakan BeginStoryboard tindakan pemicu. BeginStoryboard mendistribusikan animasi ke objek dan properti yang mereka animasikan, dan memulai papan cerita. (Untuk detail tentang proses ini, lihat Gambaran Umum Animasi dan Sistem Pengaturan Waktu.) Jika Anda memberi BeginStoryboard nama dengan menentukan propertinya Name , Anda menjadikannya papan cerita yang dapat dikontrol. Anda kemudian dapat mengontrol papan cerita secara interaktif setelah dimulai. Berikut ini adalah daftar tindakan papan cerita yang dapat dikontrol yang Anda gunakan dengan pemicu peristiwa untuk mengontrol papan cerita.

Dalam contoh berikut, tindakan papan cerita yang dapat dikontrol digunakan untuk mengontrol papan cerita secara interaktif.

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

Mengontrol Papan Cerita secara interaktif dengan Menggunakan Kode

Contoh sebelumnya telah menunjukkan cara menganimasikan menggunakan tindakan pemicu. Dalam kode, Anda juga dapat mengontrol papan cerita menggunakan metode Storyboard interaktif kelas. Agar dibuat interaktif dalam kode, Anda harus menggunakan kelebihan muatan metode papan Begin cerita yang Storyboard sesuai dan menentukan true untuk membuatnya dapat dikontrol. Lihat halaman Begin(FrameworkElement, Boolean) untuk informasi selengkapnya.

Daftar berikut menunjukkan metode yang dapat digunakan untuk memanipulasi Storyboard setelah dimulai:

Keuntungan menggunakan metode ini adalah Anda tidak perlu membuat Trigger atau TriggerAction objek; Anda hanya perlu referensi ke yang dapat Storyboard dikontrol yang ingin Anda manipulasi.

Catatan

Semua tindakan interaktif yang diambil pada Clock, dan oleh karena itu juga pada Storyboard akan terjadi pada centang berikutnya dari mesin waktu yang akan terjadi segera sebelum render berikutnya. Misalnya, jika Anda menggunakan Seek metode untuk melompat ke titik lain dalam animasi, nilai properti tidak berubah secara instan, melainkan, nilai berubah pada centang berikutnya dari mesin waktu.

Contoh berikut menunjukkan cara menerapkan dan mengontrol animasi menggunakan metode Storyboard interaktif kelas.

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

Menganimasikan dalam Gaya

Anda dapat menggunakan Storyboard objek untuk menentukan animasi dalam Style. Animasi dengan dalam Style mirip dengan Storyboard menggunakan Storyboard tempat lain, dengan tiga pengecualian berikut:

  • Anda tidak menentukan TargetName; Storyboard selalu menargetkan elemen yang Style diterapkan. Untuk menargetkan Freezable objek, Anda harus menggunakan penargetan tidak langsung. Untuk informasi selengkapnya tentang penargetan tidak langsung, lihat bagian Penargetan Tidak Langsung.

  • Anda tidak dapat menentukan SourceName untuk EventTrigger atau Trigger.

  • Anda tidak dapat menggunakan referensi sumber daya dinamis atau ekspresi pengikatan data untuk mengatur Storyboard atau nilai properti animasi. Itu karena segala sesuatu di dalam Style harus aman utas, dan sistem waktu harus FreezeStoryboard objek untuk membuatnya aman utas. Storyboard Tidak dapat dibekukan jika garis waktu atau garis waktu turunannya berisi referensi sumber daya dinamis atau ekspresi pengikatan data. Untuk informasi selengkapnya tentang pembekuan dan fitur lainnya Freezable , lihat Gambaran Umum Objek yang Dapat Dibekukan.

  • Di XAML, Anda tidak dapat mendeklarasikan penanganan aktivitas untuk Storyboard atau peristiwa animasi.

Misalnya memperlihatkan cara menentukan papan cerita dalam gaya, lihat Menganimasikan dalam contoh Gaya .

Menganimasikan di ControlTemplate

Anda dapat menggunakan Storyboard objek untuk menentukan animasi dalam ControlTemplate. Animasi dengan dalam ControlTemplate mirip dengan Storyboard menggunakan Storyboard tempat lain, dengan dua pengecualian berikut:

  • TargetName hanya dapat merujuk ke objek anak dari ControlTemplate. Jika TargetName tidak ditentukan, animasi menargetkan elemen yang ControlTemplate diterapkan.

  • SourceName untuk atau EventTrigger mungkin Trigger hanya merujuk ke objek anak dari ControlTemplate.

  • Anda tidak dapat menggunakan referensi sumber daya dinamis atau ekspresi pengikatan data untuk mengatur Storyboard atau nilai properti animasi. Itu karena segala sesuatu di dalam ControlTemplate harus aman utas, dan sistem waktu harus FreezeStoryboard objek untuk membuatnya aman utas. Storyboard Tidak dapat dibekukan jika garis waktu atau garis waktu turunannya berisi referensi sumber daya dinamis atau ekspresi pengikatan data. Untuk informasi selengkapnya tentang pembekuan dan fitur lainnya Freezable , lihat Gambaran Umum Objek yang Dapat Dibekukan.

  • Di XAML, Anda tidak dapat mendeklarasikan penanganan aktivitas untuk Storyboard atau peristiwa animasi.

Untuk contoh yang menunjukkan cara menentukan papan cerita di ControlTemplate, lihat Menganimasikan dalam contoh ControlTemplate .

Menganimasikan Saat Nilai Properti Berubah

Dalam gaya dan templat kontrol, Anda bisa menggunakan Objek pemicu untuk memulai papan cerita saat properti berubah. Misalnya, lihat Memicu Animasi Saat Nilai Properti Berubah dan Menganimasikan dalam ControlTemplate.

Animasi yang diterapkan oleh objek properti Trigger berulah dengan cara yang lebih kompleks daripada EventTrigger animasi atau animasi yang mulai menggunakan Storyboard metode. Mereka "handoff" dengan animasi yang didefinisikan oleh objek lain Trigger , tetapi menyusun dengan EventTrigger animasi yang dipicu metode dan .

Lihat juga