Tipy a triky animace

Při práci s animacemi ve WPF existuje řada tipů a triků, které vám můžou usnadnit výkon animací a ušetřit vám frustraci.

Obecné problémy

Animace pozice posuvníku nebo posuvníku zablokuje

Pokud animujete pozici posuvníku nebo posuvníku pomocí animace, která má FillBehaviorHoldEnd hodnotu (výchozí hodnota), uživatel už nebude moct posuvník nebo posuvník přesunout. Je to proto, že i když animace skončila, stále přepisuje základní hodnotu cílové vlastnosti. Pokud chcete zastavit animaci přepsání aktuální hodnoty vlastnosti, odeberte ji nebo ji dejte FillBehavior .Stop Další informace a příklad naleznete v tématu Nastavení vlastnosti po animaci pomocí scénáře.

Animace výstupu animace nemá žádný efekt

Objekt, který je výstupem jiné animace, nemůžete animovat. Pokud například použijete ObjectAnimationUsingKeyFrames k animaci RectangleFill z objektu do RadialGradientBrush objektu SolidColorBrush, nebudete moct animovat žádné vlastnosti RadialGradientBrush nebo SolidColorBrush.

Po animaci nelze změnit hodnotu vlastnosti.

V některých případech se může zdát, že nemůžete změnit hodnotu vlastnosti po animaci, i když animace skončila. Je to proto, že i když animace skončila, stále přepisuje základní hodnotu vlastnosti. Pokud chcete zastavit animaci přepsání aktuální hodnoty vlastnosti, odeberte ji nebo ji dejte FillBehavior .Stop Další informace a příklad naleznete v tématu Nastavení vlastnosti po animaci pomocí scénáře.

Změna časové osy nemá žádný vliv

I když je většina Timeline vlastností animatable a může být svázaná s daty, změna hodnot vlastností aktivního Timeline se zdá mít žádný vliv. Je to proto, že když Timeline začnete, systém časování vytvoří kopii Timeline objektu a použije ho k vytvoření objektu Clock . Úprava originálu nemá žádný vliv na kopii systému.

Timeline Aby se změny projevily, musí se jeho hodiny znovu vygenerovat a použít k nahrazení dříve vytvořených hodin. Hodiny se automaticky nevygenerují. Změny časové osy můžete použít několika způsoby:

  • Pokud je časová osa nebo patří do ní Storyboard, můžete ji změnit tak, že znovu použijete její scénář pomocí BeginStoryboard metody nebo Begin metody. To má vedlejší vliv také na restartování animace. V kódu můžete použít metodu Seek pro přechod scénáře zpět na předchozí pozici.

  • Pokud jste použili animaci přímo na vlastnost pomocí BeginAnimation metody, zavolejte metodu BeginAnimation znovu a předejte ji animaci, která byla změněna.

  • Pokud pracujete přímo na úrovni hodin, vytvořte a použijte novou sadu hodin a použijte je k nahrazení předchozí sady vygenerovaných hodin.

Další informace o časovýchoch

FillBehavior.Stop nefunguje podle očekávání

Někdy se zdá, že nastavení FillBehavior vlastnosti Stop nemá žádný vliv, například když jedna animace "ruce" na jinou, protože má HandoffBehavior nastavení SnapshotAndReplace.

Následující příklad vytvoří , Canvasa Rectangle a .TranslateTransform Bude TranslateTransform animovaný pro pohyb v Rectangle okolí Canvas.

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

Příklady v této části používají předchozí objekty k předvedení několika případů, kdy FillBehavior se vlastnost nechová podle očekávání.

FillBehavior="Stop" a HandoffBehavior s více animacemi

Někdy se zdá, že animace ignoruje jeho FillBehavior vlastnost, když je nahrazena druhou animací. Podívejte se na následující příklad, který vytvoří dva Storyboard objekty a použije je k animaci stejného TranslateTransform obrázku v předchozím příkladu.

První Storyboard, B1, animuje X vlastnost TranslateTransform od 0 do 350, který přesune obdélník 350 pixelů doprava. Když animace dosáhne konce doby trvání a přestane se přehrávat, X vlastnost se vrátí k původní hodnotě 0. V důsledku toho se obdélník přesune doprava o 350 pixelů a pak přeskočí zpět na původní pozici.

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

Druhý Storyboard, B2, také animuje X vlastnost stejného TranslateTransform. Vzhledem k tomu, že To je nastavena pouze vlastnost animace Storyboard , animace používá aktuální hodnotu vlastnosti, kterou animuje jako počáteční hodnotu.


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

Pokud při přehrávání Storyboard prvního tlačítka kliknete na druhé tlačítko, můžete očekávat následující chování:

  1. První storyboard končí a odesílá obdélník zpět do původní pozice, protože animace má znak FillBehaviorStop.

  2. Druhá storyboard se projeví a animuje z aktuální pozice, která je nyní 0 až 500.

Ale to není to, co se stane. Místo toho obdélník nepřeskočí zpět; pokračuje v pohybu doprava. Je to proto, že druhá animace používá aktuální hodnotu první animace jako počáteční hodnotu a animuje z této hodnoty na 500. Když druhá animace nahradí první, protože SnapshotAndReplaceHandoffBehavior se použije, FillBehavior nezáleží na první animaci.

FillBehavior a dokončená událost

Další příklady ukazují jiný scénář, ve kterém se zdá, že StopFillBehavior nemá žádný vliv. Příklad opět používá Storyboard k animaci X vlastnosti TranslateTransform od 0 do 350. Tentokrát se však příklad zaregistruje Completed pro událost.

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

Obslužná rutina Completed události spustí jinou Storyboard , která animuje stejnou vlastnost z aktuální hodnoty na 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

Následuje kód, který definuje sekundu Storyboard jako prostředek.

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

Když spustíte Storyboardpříkaz , můžete očekávat X , že vlastnost TranslateTransform animace od 0 do 350, pak se po dokončení vrátí na hodnotu 0 (protože má FillBehavior nastavení Stop) a pak animovat od 0 do 500. TranslateTransform Místo toho animace od 0 do 350 a potom na 500.

Důvodem je pořadí, ve kterém WPF vyvolává události a protože hodnoty vlastností jsou uloženy v mezipaměti a nejsou přepočítány, pokud není vlastnost neplatná. Událost Completed se zpracuje jako první, protože ji aktivovala kořenová časová osa (první Storyboard). V tuto chvíli vlastnost stále vrací svou animovanou hodnotu, X protože ještě nebyla zneplatněna. Druhý Storyboard používá hodnotu uloženou v mezipaměti jako počáteční hodnotu a začne animovat.

Výkon

Animace se budou dál spouštět i po přechodu mimo stránku.

Když odcházíte od Page spuštěných animací, budou se tyto animace dál přehrávat, dokud Page se neshromáždí uvolnění paměti. V závislosti na používaném navigačním systému může stránka, ze které se nacházíte, zůstat v paměti po neomezenou dobu a současně využívat prostředky s animacemi. To je nejvýraznější, když stránka obsahuje neustále spuštěné ("okolí") animace.

Z tohoto důvodu je vhodné použít Unloaded událost k odebrání animací, když přejdete mimo stránku.

Animace se dá odebrat různými způsoby. Následující techniky lze použít k odebrání animací, které patří do .Storyboard

Další technika se může použít bez ohledu na to, jak byla animace spuštěna.

Další informace o různých způsobech animace vlastností naleznete v tématu Přehled technik animace vlastností.

Použití nástroje Compose HandoffBehavior spotřebovává systémové prostředky

Pokud použijete Storyboardvlastnost nebo AnimationTimelineAnimationClock vlastnost pomocí ComposeHandoffBehavior, všechny Clock objekty dříve přidružené k této vlastnosti budou nadále využívat systémové prostředky; systém časování tyto hodiny automaticky neodebere.

Abyste se vyhnuli problémům s výkonem při použití velkého počtu hodin pomocí Compose, měli byste po dokončení odebrat psaní hodin z animované vlastnosti. Hodiny můžete odebrat několika způsoby.

Jedná se především o problém s animacemi na objektech, které mají dlouhou životnost. Když je objekt uvolněn z paměti, jeho hodiny budou také odpojeny a uvolňování paměti.

Další informace o objektech hodin naleznete v tématu Animace a časování systému Přehled.

Viz také