Tips dan Trik Animasi

Ketika bekerja dengan animasi di WPF, ada sejumlah tips dan trik yang dapat membuat animasi Anda berkinerja lebih baik dan menghemat frustrasi Anda.

Masalah Umum

Menganimasikan Posisi Bilah Gulir atau Penggoser Membekukannya

Jika Anda menganimasikan posisi bilah gulir atau penggelser menggunakan animasi yang memiliki FillBehavior nilai HoldEnd (nilai default), pengguna tidak akan dapat lagi memindahkan bilah gulir atau penggerak. Itu karena, meskipun animasi berakhir, itu masih mengesampingkan nilai dasar properti target. Untuk menghentikan animasi mengambil alih nilai properti saat ini, hapus, atau berikan FillBehavior .Stop Untuk informasi selengkapnya dan contohnya, lihat Mengatur Properti Setelah Menganimasikannya dengan Storyboard.

Menganimasikan Output Animasi Tidak Berpengaruh

Anda tidak dapat menganimasikan objek yang merupakan output dari animasi lain. Misalnya, jika Anda menggunakan ObjectAnimationUsingKeyFrames untuk menganimasikan Fill dari Rectangle dari RadialGradientBrush ke SolidColorBrush, Anda tidak dapat menganimasikan properti RadialGradientBrush atau SolidColorBrush.

Tidak Dapat Mengubah Nilai Properti setelah Menganimasikannya

Dalam beberapa kasus, mungkin muncul bahwa Anda tidak dapat mengubah nilai properti setelah dianimasikan, bahkan setelah animasi berakhir. Itu karena, meskipun animasi berakhir, itu masih mengesampingkan nilai dasar properti. Untuk menghentikan animasi mengambil alih nilai properti saat ini, hapus, atau berikan FillBehavior .Stop Untuk informasi selengkapnya dan contohnya, lihat Mengatur Properti Setelah Menganimasikannya dengan Storyboard.

Mengubah Garis Waktu Tidak Berpengaruh

Meskipun sebagian besar Timeline properti dapat dianimasikan dan dapat terikat data, mengubah nilai properti aktif Timeline tampaknya tidak berpengaruh. Itu karena, ketika Timeline dimulai, sistem waktu membuat salinan Timeline dan menggunakannya untuk membuat Clock objek. Memodifikasi asli tidak berpengaruh pada salinan sistem.

Agar mencerminkan perubahan, jamnya harus diregenerasi dan digunakan untuk mengganti jam yang Timeline dibuat sebelumnya. Jam tidak diregenerasi untuk Anda secara otomatis. Berikut ini adalah beberapa cara untuk menerapkan perubahan garis waktu:

  • Jika garis waktu adalah atau milik Storyboard, Anda dapat membuatnya mencerminkan perubahan dengan menerapkan kembali papan ceritanya menggunakan BeginStoryboard atau Begin metode . Ini memiliki efek samping dari juga menghidupkan ulang animasi. Dalam kode, Anda dapat menggunakan Seek metode untuk memajukan papan cerita kembali ke posisi sebelumnya.

  • Jika Anda menerapkan animasi langsung ke properti menggunakan BeginAnimation metode , panggil BeginAnimation metode lagi dan teruskan animasi yang telah dimodifikasi.

  • Jika Anda bekerja langsung di tingkat jam, buat dan terapkan sekumpulan jam baru dan gunakan untuk mengganti kumpulan jam yang dihasilkan sebelumnya.

Untuk informasi selengkapnya tentang garis waktu dan jam, lihat Gambaran Umum Animasi dan Sistem Pengaturan Waktu.

FillBehavior.Stop Tidak Berfungsi seperti yang Diharapkan

Ada kalanya mengatur FillBehavior properti Stop tampaknya tidak berpengaruh, seperti ketika satu animasi "lepas tangan" ke animasi lain karena memiliki HandoffBehavior pengaturan SnapshotAndReplace.

Contoh berikut membuat Canvas, a Rectangle dan TranslateTransform. TranslateTransform akan dianimasikan untuk memindahkan sekitar RectangleCanvas.

<Canvas Width="600" Height="200">
  <Rectangle 
    Canvas.Top="50" Canvas.Left="0" 
    Width="50" Height="50" Fill="Red">
    <Rectangle.RenderTransform>
      <TranslateTransform 
        x:Name="MyTranslateTransform" 
        X="0" Y="0" />
    </Rectangle.RenderTransform>
  </Rectangle>
</Canvas>

Contoh di bagian ini menggunakan objek sebelumnya untuk menunjukkan beberapa kasus di mana FillBehavior properti tidak berperilaku seperti yang mungkin Anda harapkan.

FillBehavior="Stop" dan HandoffBehavior dengan Beberapa Animasi

Terkadang tampaknya seolah-olah animasi mengabaikan propertinya FillBehavior ketika digantikan oleh animasi kedua. Ambil contoh berikut, yang membuat dua Storyboard objek dan menggunakannya untuk menganimasikan hal yang sama TranslateTransform yang ditunjukkan dalam contoh sebelumnya.

Yang pertama Storyboard, B1, menganimasikan X properti TranslateTransform dari 0 hingga 350, yang memindahkan persegi panjang 350 piksel ke kanan. Ketika animasi mencapai akhir durasinya dan berhenti diputar, X properti kembali ke nilai aslinya, 0. Akibatnya, persegi panjang bergerak ke kanan 350 piksel dan kemudian melompat kembali ke posisi aslinya.

<Button Content="Start Storyboard B1">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard x:Name="B1">
          <DoubleAnimation 
            Storyboard.TargetName="MyTranslateTransform"
            Storyboard.TargetProperty="X"
            From="0" To="350" Duration="0:0:5"
            FillBehavior="Stop"
            />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

Yang kedua Storyboard, B2, juga menganimasikan X properti dari yang sama TranslateTransform. Karena hanya To properti animasi dalam ini Storyboard yang diatur, animasi menggunakan nilai properti saat ini yang dianimasikan sebagai nilai awalnya.


<!-- Animates the same object and property as the preceding
     Storyboard. -->
<Button Content="Start Storyboard B2">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard x:Name="B2">
          <DoubleAnimation 
            Storyboard.TargetName="MyTranslateTransform"
            Storyboard.TargetProperty="X"
            To="500" Duration="0:0:5" 
            FillBehavior="Stop" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

Jika Anda mengklik tombol kedua saat yang pertama Storyboard diputar, Anda mungkin mengharapkan perilaku berikut:

  1. Papan cerita pertama berakhir dan mengirim persegi panjang kembali ke posisi aslinya, karena animasi memiliki FillBehavior dari Stop.

  2. Papan cerita kedua berlaku dan menganimasikan dari posisi saat ini, yang sekarang adalah 0, hingga 500.

Tapi bukan itu yang terjadi. Sebaliknya, persegi panjang tidak melompat kembali; terus bergerak ke kanan. Itu karena animasi kedua menggunakan nilai animasi pertama saat ini sebagai nilai awal dan menganimasikan dari nilai tersebut menjadi 500. Ketika animasi kedua menggantikan yang pertama karena SnapshotAndReplaceHandoffBehavior digunakan, FillBehavior animasi pertama tidak masalah.

FillBehavior dan Acara Selesai

Contoh berikutnya menunjukkan skenario lain di mana StopFillBehavior tampaknya tidak berpengaruh. Sekali lagi, contoh menggunakan Storyboard untuk menganimasikan X properti TranslateTransform dari 0 hingga 350. Namun, kali ini contoh mendaftar untuk peristiwa tersebut Completed .

<Button Content="Start Storyboard C">
  <Button.Triggers>
    <EventTrigger RoutedEvent="Button.Click">
      <BeginStoryboard>
        <Storyboard Completed="StoryboardC_Completed">
          <DoubleAnimation 
            Storyboard.TargetName="MyTranslateTransform"
            Storyboard.TargetProperty="X"
            From="0" To="350" Duration="0:0:5"
            FillBehavior="Stop" />
        </Storyboard>
      </BeginStoryboard>
    </EventTrigger>
  </Button.Triggers>
</Button>

Penanganan Completed aktivitas memulai yang lain Storyboard yang menganimasikan properti yang sama dari nilainya saat ini menjadi 500.

private void StoryboardC_Completed(object sender, EventArgs e)
{

    Storyboard translationAnimationStoryboard =
        (Storyboard)this.Resources["TranslationAnimationStoryboardResource"];
    translationAnimationStoryboard.Begin(this);
}
Private Sub StoryboardC_Completed(ByVal sender As Object, ByVal e As EventArgs)

    Dim translationAnimationStoryboard As Storyboard = CType(Me.Resources("TranslationAnimationStoryboardResource"), Storyboard)
    translationAnimationStoryboard.Begin(Me)
End Sub

Berikut ini adalah markup yang mendefinisikan yang kedua Storyboard sebagai sumber daya.

<Page.Resources>
  <Storyboard x:Key="TranslationAnimationStoryboardResource">
    <DoubleAnimation 
      Storyboard.TargetName="MyTranslateTransform"
      Storyboard.TargetProperty="X"
      To="500" Duration="0:0:5" />
  </Storyboard>
</Page.Resources>

Ketika Anda menjalankan Storyboard, Anda mungkin mengharapkan X properti TranslateTransform untuk menganimasikan dari 0 hingga 350, lalu kembali ke 0 setelah selesai (karena memiliki FillBehavior pengaturan Stop), lalu animasikan dari 0 hingga 500. Sebaliknya, animasi TranslateTransform dari 0 hingga 350 dan kemudian menjadi 500.

Itu karena urutan WPF menaikkan peristiwa dan karena nilai properti di-cache dan tidak dihitung ulang kecuali properti tidak valid. Peristiwa Completed diproses terlebih dahulu karena dipicu oleh garis waktu akar (yang pertama Storyboard). Saat ini, X properti masih mengembalikan nilai animasinya karena belum divalidasi. Yang kedua Storyboard menggunakan nilai cache sebagai nilai awalnya dan mulai menjiwai.

Performa

Animasi Terus Berjalan Setelah Menavigasi Jauh dari Halaman

Ketika Anda menavigasi jauh dari yang Page berisi animasi yang berjalan, animasi tersebut akan terus diputar sampai Page sampah dikumpulkan. Bergantung pada sistem navigasi yang Anda gunakan, halaman yang Anda navigasikan jauh dari mungkin tetap dalam memori untuk jumlah waktu yang tidak terbatas, sambil menggunakan sumber daya dengan animasinya. Ini paling terlihat ketika halaman berisi animasi yang terus berjalan ("sekitar").

Untuk alasan ini, ada baiknya menggunakan peristiwa untuk Unloaded menghapus animasi saat Anda menavigasi jauh dari halaman.

Ada berbagai cara untuk menghapus animasi. Teknik berikut dapat digunakan untuk menghapus animasi milik Storyboard.

Teknik berikutnya dapat digunakan terlepas dari bagaimana animasi dimulai.

  • Untuk menghapus animasi dari properti tertentu, gunakan BeginAnimation(DependencyProperty, AnimationTimeline) metode . Tentukan properti yang dianimasikan sebagai parameter pertama, dan null sebagai yang kedua. Ini akan menghapus semua jam animasi dari properti .

Untuk informasi selengkapnya tentang berbagai cara untuk menganimasikan properti, lihat Gambaran Umum Teknik Animasi Properti.

Menggunakan Compose HandoffBehavior Mengonsumsi Sumber Daya Sistem

Ketika Anda menerapkan Storyboard, , atau AnimationClock ke properti menggunakanHandoffBehaviorCompose , objek apa pun Clock yang sebelumnya terkait dengan properti tersebut terus menggunakan sumber daya sistem; sistem waktu tidak akan menghapus jam AnimationTimelineini secara otomatis.

Untuk menghindari masalah performa saat Anda menerapkan sejumlah besar jam menggunakan Compose, Anda harus menghapus jam pembuatan dari properti animasi setelah selesai. Ada beberapa cara untuk menghapus jam.

Ini terutama masalah untuk animasi pada objek yang memiliki masa pakai yang lama. Ketika objek dikumpulkan sampah, jamnya juga akan terputus dan sampah dikumpulkan.

Untuk informasi selengkapnya tentang objek jam, lihat Gambaran Umum Animasi dan Sistem Pengaturan Waktu.

Baca juga