Bagikan melalui


Animasi bingkai kunci dan animasi fungsi permudah

Animasi bingkai kunci linier, animasi bingkai kunci dengan nilai KeySpline , atau fungsi pengurangan adalah tiga teknik berbeda untuk skenario yang kira-kira sama: membuat animasi papan cerita yang sedikit lebih kompleks, dan yang menggunakan perilaku animasi nonlinear dari status awal ke status akhir.

Prasyarat

Pastikan Anda telah membaca topik Storyboarded Animations. Topik ini dibangun berdasarkan konsep animasi yang dijelaskan dalam animasi Storyboarded dan tidak akan membahasnya lagi. Misalnya, animasi dengan storyboard menjelaskan cara menargetkan animasi, storyboard sebagai sumber daya, nilai properti Garis Waktu seperti Durasi, FillBehavior, dan sebagainya.

Menganimasikan menggunakan animasi bingkai kunci

Animasi key-frame memungkinkan lebih dari satu nilai target yang dicapai pada titik sepanjang garis waktu animasi. Dengan kata lain, setiap bingkai kunci dapat menentukan nilai menengah yang berbeda, dan bingkai kunci terakhir yang dicapai adalah nilai animasi akhir. Dengan menentukan beberapa nilai untuk dianimasikan, Anda dapat membuat animasi yang lebih kompleks. Animasi bingkai kunci juga memungkinkan logika interpolasi yang berbeda, yang masing-masing diimplementasikan sebagai subkelas KeyFrame yang berbeda per jenis animasi. Secara khusus, setiap jenis animasi keyframe memiliki variasi Diskrit, Linier, Spline, dan Penghalusan dari kelas KeyFrame masing-masing untuk menentukan bingkai kunci. Misalnya, untuk menentukan animasi yang menargetkan Double dan menggunakan bingkai kunci, Anda dapat mendeklarasikan bingkai kunci dengan DiscreteDoubleKeyFrame, LinearDoubleKeyFrame, SplineDoubleKeyFrame, dan EasingDoubleKeyFrame. Anda dapat menggunakan salah satu dan semua jenis ini dalam satu koleksi KeyFrames , untuk mengubah interpolasi setiap kali bingkai kunci baru tercapai.

Untuk perilaku interpolasi, setiap bingkai kunci mengontrol interpolasi hingga waktu KeyTime tercapai. Nilainya tercapai pada saat itu juga. Jika ada lebih banyak bingkai kunci di luarnya, nilai kemudian menjadi nilai awal untuk bingkai kunci berikutnya secara berurutan.

Pada awal animasi, jika bingkai kunci dengan KeyTime "0:0:0" tidak ditemukan, nilai awalnya sesuai dengan nilai non-animasi dari properti tersebut. Ini mirip dengan bagaimana animasi From/To/By bertindak ketika tidak ada From.

Durasi animasi bingkai kunci secara implisit durasinya sama dengan nilai KeyTime tertinggi yang diatur dalam salah satu bingkai kuncinya. Anda dapat mengatur Durasi eksplisit jika mau, tetapi berhati-hatilah agar tidak lebih pendek dari KeyTime di bingkai kunci Anda sendiri, jika tidak, Anda akan memotong bagian dari animasi.

Selain Durasi, Anda dapat mengatur semua properti Berbasis Garis Waktu pada animasi bingkai kunci, seperti yang dapat Anda gunakan dengan animasi Dari/Ke/Menurut , karena kelas animasi bingkai kunci juga berasal dari Garis Waktu. Ini adalah:

  • AutoReverse: setelah frame kunci terakhir tercapai, frame diulang dalam urutan terbalik dari akhir. Ini menggandakan durasi animasi yang tampak.
  • BeginTime: menunda awal animasi. Garis waktu untuk nilai KeyTime dalam bingkai tidak mulai dihitung hingga BeginTime tercapai, sehingga tidak ada risiko memotong bingkai
  • FillBehavior: mengontrol apa yang terjadi ketika bingkai kunci terakhir tercapai. FillBehavior tidak berpengaruh pada bingkai kunci perantara apa pun.
  • RepeatBehavior:
    • Jika diatur ke Selamanya, maka bingkai kunci dan garis waktunya berulang tanpa batas.
    • Jika diatur ke jumlah perulangan, garis waktu akan berulang berkali-kali.
    • Jika diatur ke Durasi, garis waktu akan diulang hingga waktu tersebut tercapai. Ini mungkin memotong bagian animasi melalui urutan bingkai kunci, jika itu bukan faktor bilangan bulat dari durasi implisit garis waktu.
  • SpeedRatio (tidak umum digunakan)

Bingkai kunci linier

Bingkai kunci linier menghasilkan interpolasi linier sederhana dari nilai hingga KeyTime bingkai tercapai. Perilaku interpolasi ini paling mirip dengan animasi From/To/By yang lebih sederhana yang dijelaskan dalam topik animasi yang dibuat dengan Storyboard.

Berikut cara menggunakan animasi bingkai kunci untuk menskalakan tinggi render persegi panjang, menggunakan bingkai kunci linier. Contoh ini menjalankan animasi di mana tinggi persegi panjang meningkat sedikit dan linier selama 4 detik pertama, lalu menskalakan dengan cepat untuk detik terakhir sampai persegi panjang menggandakan tinggi awal.

<StackPanel>
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimationUsingKeyFrames
              Storyboard.TargetName="myRectangle"
              Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0"/>
                <LinearDoubleKeyFrame Value="1.2" KeyTime="0:0:4"/>
                <LinearDoubleKeyFrame Value="2" KeyTime="0:0:5"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </StackPanel.Resources>
</StackPanel>

Bingkai kunci diskrit

Bingkai kunci diskrit tidak menggunakan interpolasi sama sekali. Ketika KeyTime tercapai, Nilai baru hanya diterapkan. Tergantung pada properti UI mana yang sedang dianimasikan, ini sering menghasilkan animasi yang tampaknya "melompat". Pastikan bahwa ini adalah perilaku estetika yang benar-benar Anda inginkan. Anda dapat meminimalkan lompatan yang jelas dengan meningkatkan jumlah bingkai kunci yang Anda deklarasikan, tetapi jika animasi yang halus adalah tujuan Anda, Anda mungkin lebih baik menggunakan bingkai kunci linier atau spline sebagai gantinya.

Nota

Bingkai kunci diskrit adalah satu-satunya cara untuk menganimasikan nilai yang bukan tipe Double, Point, dan Color, dengan DiscreteObjectKeyFrame. Kita akan membahas ini secara lebih rinci nanti dalam topik ini.

Bingkai kunci spline

Bingkai kunci spline membuat transisi variabel antar nilai sesuai dengan nilai properti KeySpline . Properti ini menentukan titik kontrol pertama dan kedua dari kurva Bezier, yang menjelaskan akselerasi animasi. Pada dasarnya, KeySpline mendefinisikan hubungan fungsi dari waktu ke waktu di mana grafik waktu fungsi adalah bentuk kurva Bezier tersebut. Anda biasanya menentukan nilai KeySpline dalam string atribut singkat XAML yang memiliki empat nilai Ganda yang dipisahkan oleh spasi atau koma. Nilai-nilai ini adalah pasangan "X,Y" untuk dua titik kontrol kurva Bezier. "X" adalah waktu dan "Y" adalah pengubah fungsi ke nilai . Setiap nilai harus selalu antara 0 dan 1 inklusif. Tanpa modifikasi titik kontrol ke KeySpline, garis lurus dari 0,0 hingga 1,1 adalah representasi fungsi dari waktu ke waktu untuk interpolasi linier. Titik kontrol Anda mengubah bentuk kurva tersebut dan dengan demikian perilaku fungsi dari waktu ke waktu untuk animasi spline. Mungkin yang terbaik adalah melihat ini secara visual sebagai grafik.

Contoh berikutnya ini menunjukkan tiga bingkai kunci berbeda yang diterapkan ke animasi, dengan yang terakhir menjadi animasi spline kunci untuk nilai Double (SplineDoubleKeyFrame). Perhatikan string "0.6,0.0 0.9,0.00" yang diterapkan untuk KeySpline. Ini menghasilkan kurva di mana animasi tampaknya berjalan lambat pada awalnya tetapi kemudian dengan cepat mencapai nilai tepat sebelum KeyTime tercapai.

<Storyboard x:Name="myStoryboard">
    <!-- Animate the TranslateTransform's X property
        from 0 to 350, then 50,
        then 200 over 10 seconds. -->
    <DoubleAnimationUsingKeyFrames
        Storyboard.TargetName="MyAnimatedTranslateTransform"
        Storyboard.TargetProperty="X"
        Duration="0:0:10" EnableDependentAnimation="True">

        <!-- Using a LinearDoubleKeyFrame, the rectangle moves 
            steadily from its starting position to 500 over 
            the first 3 seconds.  -->
        <LinearDoubleKeyFrame Value="500" KeyTime="0:0:3"/>

        <!-- Using a DiscreteDoubleKeyFrame, the rectangle suddenly 
            appears at 400 after the fourth second of the animation. -->
        <DiscreteDoubleKeyFrame Value="400" KeyTime="0:0:4"/>

        <!-- Using a SplineDoubleKeyFrame, the rectangle moves 
            back to its starting point. The
            animation starts out slowly at first and then speeds up. 
            This KeyFrame ends after the 6th second. -->
        <SplineDoubleKeyFrame KeySpline="0.6,0.0 0.9,0.00" Value="0" KeyTime="0:0:6"/>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Meringankan bingkai kunci

Bingkai kunci easing adalah bingkai kunci tempat interpolasi diterapkan, dan fungsi interpolasi dari waktu ke waktu dikendalikan oleh beberapa rumus matematika yang sudah ditentukan sebelumnya. Anda sebenarnya dapat menghasilkan hasil yang hampir sama dengan bingkai kunci spline seperti halnya dengan beberapa jenis fungsi easing, tetapi ada juga beberapa fungsi easing, seperti BackEase, yang tidak dapat Anda reproduksi dengan spline.

Untuk menerapkan fungsi pelingan ke bingkai kunci pelingan, Anda mengatur properti EasingFunction sebagai elemen properti di XAML untuk bingkai kunci tersebut. Untuk nilai , tentukan elemen objek untuk salah satu jenis fungsi yang meringankan.

Contoh ini menerapkan CubicEase dan kemudian BounceEase sebagai bingkai kunci berturut-turut ke DoubleAnimation untuk membuat efek memantul.

<Storyboard x:Name="myStoryboard">
    <DoubleAnimationUsingKeyFrames Duration="0:0:10"
        Storyboard.TargetProperty="Height"
        Storyboard.TargetName="myEllipse">

        <!-- This keyframe animates the ellipse up to the crest 
            where it slows down and stops. -->
        <EasingDoubleKeyFrame Value="-300" KeyTime="00:00:02">
            <EasingDoubleKeyFrame.EasingFunction>
                <CubicEase/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>

        <!-- This keyframe animates the ellipse back down and makes
            it bounce. -->
        <EasingDoubleKeyFrame Value="0" KeyTime="00:00:06">
            <EasingDoubleKeyFrame.EasingFunction>
                <BounceEase Bounces="5"/>
            </EasingDoubleKeyFrame.EasingFunction>
        </EasingDoubleKeyFrame>
    </DoubleAnimationUsingKeyFrames>
</Storyboard>

Ini hanyalah satu contoh fungsi yang meringankan. Kita akan membahas lebih banyak di bagian berikutnya.

Fungsi penguraian

Fungsi kemudahan memungkinkan Anda menerapkan rumus matematika kustom ke animasi Anda. Operasi matematika sering berguna untuk menghasilkan animasi yang mensimulasikan fisika dunia nyata dalam sistem koordinat 2-D. Misalnya, Anda mungkin ingin objek memantul dengan realistis atau bertindak seolah-olah berada di pegas. Anda dapat menggunakan bingkai kunci atau bahkan dari/ke/oleh animasi untuk mendekati efek ini, tetapi akan memerlukan banyak pekerjaan dan animasi akan kurang akurat daripada menggunakan rumus matematika.

Fungsi kemudahan dapat diterapkan ke animasi dengan tiga cara:

Berikut adalah daftar fungsi kemudahan:

  • BackEase: Menarik kembali gerakan animasi sedikit sebelum mulai menganimasikan di jalur yang ditunjukkan.
  • BounceEase: Membuat efek memantul.
  • CircleEase: Membuat animasi yang mempercepat atau memperlambat menggunakan fungsi melingkar.
  • CubicEase: Membuat animasi yang mempercepat atau memperlambat menggunakan rumus f(t) = t^3.
  • ElasticEase: Membuat animasi yang menyerupai pegas bergetar bolak-balik sampai berhenti.
  • ExponentialEase: Membuat animasi yang mempercepat atau memperlambat menggunakan rumus eksponensial.
  • PowerEase: Membuat animasi yang mempercepat atau mempercepat menggunakan rumus f(t) = tp di mana p sama dengan properti Daya .
  • QuadraticEase: Membuat animasi yang mempercepat atau memperlambat menggunakan rumus f(t) = t^2.
  • QuarticEase: Membuat animasi yang mempercepat atau melambat menggunakan rumus f(t) = t^4.
  • QuinticEase: Buat animasi yang mempercepat atau memperlambat menggunakan rumus f(t) = t5.
  • SineEase: Membuat animasi yang mempercepat atau memperlambat menggunakan rumus sinus.

Beberapa fungsi pemulus memiliki sifatnya sendiri. Misalnya, BounceEase memiliki dua properti Bounces dan Bounciness yang memodifikasi perilaku fungsi dari waktu ke waktu dari BounceEase tertentu. Fungsi pelingan lainnya seperti CubicEase tidak memiliki properti selain properti EasingMode yang dibagikan semua fungsi pelingan, dan selalu menghasilkan perilaku fungsi dari waktu ke waktu yang sama.

Beberapa fungsi kemudahan ini memiliki sedikit tumpang tindih, tergantung pada bagaimana Anda mengatur properti pada fungsi kemudahan yang memiliki properti. Misalnya, QuadraticEase sama persis dengan PowerEase dengan Power sama dengan 2. Dan CircleEase pada dasarnya adalah ExponentialEase nilai default.

Fungsi pelingan BackEase unik karena dapat mengubah nilai di luar rentang normal sebagaimana diatur oleh Dari/Ke atau nilai bingkai kunci. Animasi dimulai dengan mengubah nilai ke arah yang berlawanan dari yang diharapkan pada perilaku Dari/Ke normal, kembali ke nilai Dari atau nilai awal lagi, lalu menjalankan animasi seperti biasa.

Dalam contoh sebelumnya, kami menunjukkan cara mendeklarasikan fungsi pengurangan untuk animasi bingkai kunci. Sampel berikutnya ini menerapkan fungsi pengurangan ke animasi Dari/Ke/Menurut .

<StackPanel x:Name="LayoutRoot" Background="White">
    <StackPanel.Resources>
        <Storyboard x:Name="myStoryboard">
            <DoubleAnimation From="30" To="200" Duration="00:00:3" 
                Storyboard.TargetName="myRectangle" 
                Storyboard.TargetProperty="(UIElement.RenderTransform).(ScaleTransform.ScaleY)">
                <DoubleAnimation.EasingFunction>
                    <BounceEase Bounces="2" EasingMode="EaseOut" 
                                Bounciness="2"/>
                </DoubleAnimation.EasingFunction>
            </DoubleAnimation>
        </Storyboard>
    </StackPanel.Resources>
    <Rectangle x:Name="myRectangle" Fill="Blue" Width="200" Height="30"/>
</StackPanel>

Saat fungsi easing diterapkan ke animasi Dari/Ke/Dengan, fungsi ini mengubah karakteristik interpolasi nilai dari Dari ke Ke selama Durasi animasi. Tanpa fungsi yang meringankan, itu akan menjadi interpolasi linier.

Animasi nilai objek diskrit

Satu jenis animasi layak disebutkan khusus karena ini adalah satu-satunya cara Anda dapat menerapkan nilai animasi ke properti yang bukan tipe Ganda, Titik, atau Warna. Ini adalah animasi key-frame ObjectAnimationUsingKeyFrames. Menganimasikan menggunakan nilai Objek berbeda karena tidak ada kemungkinan menginterpolasi nilai di antara bingkai. Ketika KeyTime bingkai tercapai, nilai animasi segera diatur ke nilai yang ditentukan dalam Nilai bingkai kunci. Karena tidak ada interpolasi, hanya ada satu bingkai kunci yang Anda gunakan dalam koleksi bingkai kunci ObjectAnimationUsingKeyFrames : DiscreteObjectKeyFrame.

NilaiDiscreteObjectKeyFrame sering diatur menggunakan sintaks elemen properti, karena nilai objek yang Anda coba atur sering tidak dapat diekspresikan sebagai string untuk mengisi Nilai dalam sintaks atribut. Anda masih dapat menggunakan sintaks atribut jika Anda menggunakan referensi seperti StaticResource.

Satu tempat Anda akan melihat ObjectAnimationUsingKeyFrames yang digunakan dalam templat default adalah ketika properti templat mereferensikan sumber daya Brush . Sumber daya ini adalah objek SolidColorBrush , bukan hanya nilai Warna , dan mereka menggunakan sumber daya yang didefinisikan sebagai tema sistem (ThemeDictionaries). Mereka dapat ditetapkan langsung ke nilai jenis Brush seperti TextBlock.Foreground dan tidak perlu menggunakan penargetan tidak langsung. Tetapi karena SolidColorBrush bukan Double, Point, atau Color, Anda harus menggunakan ObjectAnimationUsingKeyFrames untuk menggunakan sumber daya.

<Style x:Key="TextButtonStyle" TargetType="Button">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid Background="Transparent">
                    <TextBlock x:Name="Text"
                        Text="{TemplateBinding Content}"/>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal"/>
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
...
                       </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Anda juga dapat menggunakan ObjectAnimationUsingKeyFrames untuk menganimasikan properti yang menggunakan nilai enumerasi. Berikut adalah contoh lain dari gaya yang disebut yang berasal dari templat default Windows Runtime. Perhatikan cara mengatur properti Visibilitas yang mengambil konstanta enumerasi Visibilitas . Dalam hal ini Anda dapat mengatur nilai menggunakan sintaks atribut. Anda hanya memerlukan nama konstanta yang tidak memenuhi syarat dari enumerasi untuk mengatur properti dengan nilai enumerasi, misalnya "Diciutkan".

<Style x:Key="BackButtonStyle" TargetType="Button">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="Button">
          <Grid x:Name="RootGrid">
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="CommonStates">
              <VisualState x:Name="Normal"/>
...           <VisualState x:Name="Disabled">
                <Storyboard>
                  <ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame Value="Collapsed" KeyTime="0"/>
                  </ObjectAnimationUsingKeyFrames>
                </Storyboard>
              </VisualState>
            </VisualStateGroup>
...
          </VisualStateManager.VisualStateGroups>
        </Grid>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

Anda dapat menggunakan lebih dari satu rangkaian bingkai DiscreteObjectKeyFrame untuk rangkaian ObjectAnimationUsingKeyFrames . Ini mungkin cara yang menarik untuk membuat animasi "peragaan slide" dengan menganimasikan nilai Image.Source, sebagai contoh skenario di mana beberapa nilai objek mungkin berguna.