Nota
O acesso a esta página requer autorização. Pode tentar iniciar sessão ou alterar os diretórios.
O acesso a esta página requer autorização. Pode tentar alterar os diretórios.
Este tópico mostra como usar Storyboard objetos para organizar e aplicar animações. Ele descreve como manipular Storyboard objetos interativamente e descreve a sintaxe de direcionamento de propriedade indireta.
Pré-requisitos
Para entender este tópico, você deve estar familiarizado com os diferentes tipos de animação e seus recursos básicos. Para obter uma introdução à animação, consulte a Visão geral da animação. Você também deve saber como usar propriedades anexadas. Para obter mais informações sobre propriedades anexadas, consulte Visão geral de propriedades anexadas.
O que é um Storyboard
As animações não são o único tipo útil de linha do tempo. Outras classes de linha do tempo são fornecidas para ajudá-lo a organizar conjuntos de linhas do tempo e aplicar linhas do tempo às propriedades. As linhas do tempo do contêiner derivam da TimelineGroup classe e incluem ParallelTimeline e Storyboard.
A Storyboard é um tipo de linha temporal contêiner que fornece informações de direcionamento para as linhas temporais que contém. Um Storyboard pode conter qualquer tipo de Timeline, incluindo outras linhas do tempo contêiner e animações. Storyboard Os objetos permitem combinar linhas do tempo que afetam uma variedade de objetos e propriedades em uma única árvore de linha do tempo, facilitando a organização e o controle de comportamentos complexos de temporização. Por exemplo, suponha que você queira um botão que faça essas três coisas.
Aumente e mude de cor quando o usuário seleciona o botão.
Encolhe-se e, em seguida, volta ao seu tamanho original quando é clicado.
Encolher e desvanecer para 50% de opacidade quando ele ficar desativado.
Nesse caso, você tem vários conjuntos de animações que se aplicam ao mesmo objeto e deseja reproduzir em momentos diferentes, dependendo do estado do botão. Storyboard Os objetos permitem organizar animações e aplicá-las em grupos a um ou mais objetos.
Onde você pode usar um Storyboard
A Storyboard pode ser usado para animar propriedades de dependência de classes animáveis (para obter mais informações sobre o que torna uma classe animável, consulte a Visão geral da animação). No entanto, uma vez que o storyboarding é um recurso ao nível da estrutura, o objeto deve pertencer a NameScope, FrameworkElement ou FrameworkContentElement.
Por exemplo, você pode usar a Storyboard para fazer o seguinte:
Animar um SolidColorBrush (elemento não-estrutura) que pinta o plano de fundo de um botão (um tipo de FrameworkElement),
Animar um SolidColorBrush (elemento não-framework) que colore o preenchimento de um GeometryDrawing (elemento não-framework) exibido através de um Image (FrameworkElement).
No código, anime um SolidColorBrush declarado por uma classe que também contenha um FrameworkElement, se o SolidColorBrush registou o seu nome com aquele FrameworkElement.
No entanto, não se pode usar uma Storyboard para animar um SolidColorBrush que não registou o seu nome com uma FrameworkElement ou FrameworkContentElement, ou não foi usado para definir uma propriedade de uma FrameworkElement ou FrameworkContentElement.
Como aplicar animações com um Storyboard
Para usar um Storyboard para organizar e aplicar animações, adicione as animações como linhas de tempo filhas do Storyboard. A classe Storyboard fornece propriedades anexadas Storyboard.TargetName e Storyboard.TargetProperty. Você define essas propriedades em uma animação para especificar seu objeto e propriedade de destino.
Para aplicar animações aos seus destinos, comece a usar uma ação de gatilho Storyboard ou um método. Em XAML, você utiliza um objeto BeginStoryboard com EventTrigger, Trigger ou DataTrigger. No código, você também pode usar o Begin método.
A tabela a seguir mostra os diferentes locais onde cada Storyboard técnica de início é suportada: por instância, estilo, modelo de controle e modelo de dados. "Por instância" refere-se à técnica de aplicar uma animação ou storyboard diretamente a instâncias de um objeto, em vez de em um estilo, modelo de controle ou modelo de dados.
A criação do Storyboard é iniciada usando… | Por cada instância | Estilo | Modelo de controlo | Modelo de dados | Exemplo |
---|---|---|---|---|---|
BeginStoryboard e um EventTrigger | Sim | Sim | Sim | Sim | Animar uma Propriedade Usando um Roteiro de Animação |
BeginStoryboard e um imóvel Trigger | Não | Sim | Sim | Sim | acionar uma animação quando um valor de propriedade é alterado |
BeginStoryboard e um imóvel MultiTrigger | Não | Sim | Sim | Sim | Exemplo de classe MultiTrigger |
BeginStoryboard e um DataTrigger | Não | Sim | Sim | Sim | Como: Acionar uma animação quando os dados são alterados |
BeginStoryboard e um MultiDataTrigger | Não | Sim | Sim | Sim | Exemplo de classe MultiDataTrigger |
Begin método | Sim | Não | Não | Não | Animar uma Propriedade Usando um Roteiro de Animação |
O exemplo a seguir usa a Storyboard para animar o Width de um elemento Rectangle e o Color de um SolidColorBrush usado para pintar esse mesmo 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;
}
}
}
As seções a seguir descrevem as propriedades anexadas TargetName e TargetProperty em mais detalhes.
Segmentando elementos da estrutura, elementos de conteúdo da estrutura e elementos congeláveis
A seção anterior mencionou que, para uma animação encontrar seu destino, ela deve saber o nome do alvo e a propriedade a ser animada. Especificar a propriedade a ser animada é simples: basta definir TargetProperty
com o nome da propriedade a ser animada. Você especifica o nome do objeto cuja propriedade você deseja animar definindo a Storyboard.TargetName propriedade na animação.
Atenção
Embora você possa usar a Target
propriedade para vincular diretamente a um objeto como uma alternativa ao TargetName
, ele não é serializável. Não há garantia de que o Target
objeto possa ser referenciado corretamente em XAML.
Para que a TargetName propriedade funcione, o objeto de destino deve ter um nome. Atribuir um nome a um FrameworkElement ou a FrameworkContentElement em XAML é diferente de atribuir um nome a um Freezable objeto.
Os elementos da estrutura são as classes que herdam da FrameworkElement classe. Exemplos de elementos da estrutura incluem Window, DockPanel, Buttone Rectangle. Essencialmente, todas as janelas, painéis e controles são elementos. Os elementos de conteúdo da estrutura são as classes que herdam da FrameworkContentElement classe. Exemplos de elementos de conteúdo da estrutura incluem FlowDocument e Paragraph. Se você não tiver certeza se um tipo é um elemento de estrutura ou um elemento de conteúdo de estrutura, verifique se ele tem uma propriedade Name. Se isso acontecer, provavelmente é um elemento de estrutura ou um elemento de conteúdo estruturado. Para ter certeza, verifique a seção Hierarquia de herança de sua página de tipo.
Para habilitar o direcionamento de um elemento de estrutura ou de um elemento de conteúdo de estrutura em XAML, defina sua Name propriedade. No código, deves também usar o método RegisterName para registar o nome do elemento com o elemento para o qual criaste um NameScope.
O exemplo a seguir, retirado do exemplo anterior, atribui o nome MyRectangle
a Rectangle, um tipo de 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);
Depois que ele tiver um nome, você poderá animar uma propriedade desse elemento.
<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 tipos são as classes que herdam da classe Freezable. Exemplos de Freezable incluem SolidColorBrush, RotateTransform, e GradientStop.
Para habilitar o direcionamento de um Freezable por uma animação em XAML, use a diretiva x:Name para atribuir-lhe um nome. No código, você usa o RegisterName método para registrar seu nome com o elemento para o qual você criou um NameScope.
O exemplo a seguir atribui um nome a um Freezable objeto.
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
O objeto pode então ser direcionado por uma animação.
<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 objetos usam escopos de nome para resolver a propriedade TargetName. Para obter mais informações sobre escopos de nome WPF, consulte Namescopes WPF XAML. Se a TargetName propriedade for omitida, a animação terá como alvo o elemento no qual ela é definida ou, no caso de estilos, o elemento estilizado.
Às vezes, um nome não pode ser atribuído a um Freezable objeto. Por exemplo, se um Freezable for declarado como um recurso ou usado para definir um valor de propriedade em um estilo, ele não poderá receber um nome. Como não tem um nome, não pode ser direcionado diretamente, mas pode ser direcionado indiretamente. As seções a seguir descrevem como usar a segmentação indireta.
Direcionamento indireto
Há momentos em que Freezable não pode ser direcionado diretamente por uma animação, como quando Freezable é declarado como recurso ou usado para definir um valor de propriedade em um estilo. Nesses casos, mesmo que você não possa direcioná-lo diretamente, você ainda pode animar o Freezable objeto. Em vez de definir a TargetName propriedade com o nome do Freezable, você dá a ele o nome do elemento ao qual o Freezable "pertence". Por exemplo, um SolidColorBrush elemento usado para definir o Fill de um retângulo pertence a esse retângulo. Para animar o pincel, tu definirias a animação TargetProperty com uma cadeia de propriedades que começa na propriedade do elemento da estrutura ou do elemento de conteúdo da estrutura em que Freezable é utilizado para definir e termina na propriedade Freezable que se pretende animar.
<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);
Note que, se o Freezable for congelado, um clone será feito, e esse clone será animado. Quando isso acontece, a propriedade do HasAnimatedProperties objeto original continua a retornar false
, porque o objeto original não é realmente animado. Para obter mais informações sobre clonagem, consulte a Visão geral de objetos Freezable.
Observe também que, ao usar a segmentação indireta de propriedades, é possível direcionar objetos que não existem. Por exemplo, você pode supor que o Background de um determinado botão foi definido com um SolidColorBrush e tentar animar sua Cor, quando na verdade um LinearGradientBrush foi usado para definir o Plano de Fundo do botão. Nestes casos, nenhuma exceção é lançada; A animação não consegue ter um efeito visível porque LinearGradientBrush não reage a alterações na Color propriedade.
As seções a seguir descrevem a sintaxe de direcionamento de propriedade indireta com mais detalhes.
Direcionar indiretamente uma propriedade de um Freezable no XAML
Para direcionar uma propriedade de um congelável em XAML, use a sintaxe a seguir.
Sintaxe da propriedade |
---|
ElementPropertyName. FreezablePropertyName |
Onde
ElementPropertyName é a propriedade da qual o FrameworkElementFreezable é usado para definir, e
FreezablePropertyName é a propriedade do Freezable para animar.
O código a seguir mostra como animar o Color de um SolidColorBrush usado para definir o Fill de um elemento retângulo.
<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>
Às vezes, é necessário apontar para um objeto que pode ser congelado dentro de uma coleção ou matriz.
Para direcionar um objeto congelável, como encontrado numa coleção, utilize a seguinte sintaxe de caminho.
Sintaxe do caminho |
---|
ElementPropertyName.Children[ CollectionIndex]. FreezablePropertyName |
Onde CollectionIndex é o índice do objeto em sua matriz ou coleção.
Por exemplo, suponha que um retângulo tenha um TransformGroup recurso aplicado à sua RenderTransform propriedade e você queira animar uma das transformações que ele contém.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
O código a seguir mostra como animar a AngleRotateTransform propriedade do mostrado no exemplo anterior.
<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>
Visando indiretamente uma propriedade de um Freezable in Code
No código, você cria um PropertyPath objeto. Ao criar o PropertyPath, você especifica a Path e PathParameters.
Para criar PathParameterso , crie uma matriz do tipo DependencyProperty que contenha uma lista de campos de identificador de propriedade de dependência. O primeiro campo identificador é para a propriedade do FrameworkElement ou FrameworkContentElement que o Freezable é usado para definir. O próximo campo identificador representa a propriedade do Freezable a direcionar. Pense nisso como uma cadeia de propriedades que conecta o Freezable ao FrameworkElement objeto.
A seguir está um exemplo de uma cadeia de propriedades de dependência que tem como alvo o Color de um SolidColorBrush usado para definir o Fill de um elemento retângulo.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
Você também precisa especificar um Patharquivo . A Path é um String que diz ao Path como interpretar o seu PathParameters. Ele usa a sintaxe a seguir.
Sintaxe do caminho da propriedade |
---|
(
OwnerPropertyArrayIndex).( FreezablePropertyArrayIndex) |
Onde
OwnerPropertyArrayIndex é o DependencyProperty índice da matriz que contém o identificador da propriedade do FrameworkElement objeto que o Freezable é usado para definir, e
FreezablePropertyArrayIndex é o índice da matriz que contém o identificador da propriedade a ser direcionada.
O exemplo a seguir mostra o Path que acompanharia o PathParameters definido no exemplo anterior.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
O exemplo a seguir combina o código nos exemplos anteriores para animar o Color de um SolidColorBrush usado para definir o Fill de um elemento retângulo.
// 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);
Às vezes, é necessário apontar para um objeto que pode ser congelado dentro de uma coleção ou matriz. Por exemplo, suponha que um retângulo tenha um TransformGroup recurso aplicado à sua RenderTransform propriedade e você queira animar uma das transformações que ele contém.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Para direcionar um Freezable contido numa coleção, use a seguinte sintaxe de caminho.
Sintaxe do caminho |
---|
(
OwnerPropertyArrayIndex).( CollectionChildrenPropertyArrayIndex) [ CollectionIndex].( FreezablePropertyArrayIndex) |
Onde CollectionIndex é o índice do objeto em sua matriz ou coleção.
Para direcionar a propriedade Angle do RotateTransform, a segunda transformação no TransformGroup, deve utilizar os seguintes Path e 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);
O exemplo a seguir mostra o código completo para animar o Angle de um RotateTransform contido num 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);
Segmentação indireta com um Freezable como ponto de partida
As seções anteriores descreveram como direcionar indiretamente a Freezable começando com um FrameworkElement ou FrameworkContentElement e criando uma cadeia de propriedades para uma Freezable subpropriedade. Você também pode usar a Freezable como ponto de partida e direcionar indiretamente uma de suas Freezable subpropriedades. Uma restrição adicional aplica-se ao usar um Freezable como ponto de partida para o direcionamento indireto: o Freezable inicial e todos os Freezable entre ele e a subpropriedade indiretamente visada não devem estar congelados.
Controlando interativamente um Storyboard em XAML
Para iniciar um storyboard em Extensible Application Markup Language (XAML), utilize uma ação disparadora BeginStoryboard. BeginStoryboard distribui as animações para os objetos e propriedades a que animam e inicia o storyboard. (Para obter detalhes sobre esse processo, consulte a Visão geral do sistema de animação e cronometragem.) Se você der um BeginStoryboard nome especificando sua Name propriedade, você o tornará um storyboard controlável. Em seguida, você pode controlar interativamente o storyboard depois que ele for iniciado. Veja a seguir uma lista de ações controláveis do storyboard que você usa com gatilhos de eventos para controlar um storyboard.
PauseStoryboard: Pausa o storyboard.
ResumeStoryboard: Retoma um storyboard pausado.
SetStoryboardSpeedRatio: Altera a velocidade do storyboard.
SkipStoryboardToFill: Avança um storyboard até o final do período de preenchimento, se tiver um.
StopStoryboard: Para o storyboard.
RemoveStoryboard: Elimina o storyboard.
No exemplo a seguir, ações de storyboard controláveis são usadas para controlar de forma interativa um storyboard.
<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>
Controlando interativamente um Storyboard usando código
Os exemplos anteriores mostraram como animar usando ações de gatilho. No código, você também pode controlar um storyboard usando métodos interativos da Storyboard classe. Para tornar um Storyboard interativo no código, deve-se usar a sobrecarga apropriada do método do storyboard Begin e especificar true
para o tornar controlável. Consulte a Begin(FrameworkElement, Boolean) página para obter mais informações.
A lista a seguir mostra os métodos que podem ser usados para manipular um Storyboard depois que ele foi iniciado:
A vantagem de usar esses métodos é que você não precisa criar Trigger ou TriggerAction objetos, você só precisa de uma referência para o controlável Storyboard que você deseja manipular.
Observação
Todas as ações interativas realizadas em um Clock, e, portanto, também em um Storyboard, ocorrerão no próximo tick do motor de temporização, o que acontecerá um pouco antes da renderização seguinte. Por exemplo, se você usar o Seek método para saltar para outro ponto em uma animação, o valor da propriedade não será alterado instantaneamente, em vez disso, o valor será alterado no próximo tick do mecanismo de temporização.
O exemplo a seguir mostra como aplicar e controlar animações usando os métodos interativos da Storyboard classe.
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
Animar num Estilo
Você pode usar Storyboard objetos para definir animações em um Style. Animar com um Storyboard num Style é semelhante a usar um Storyboard noutro lugar, com três exceções.
Você não especifica um TargetName; o Storyboard sempre tem como alvo o elemento ao qual o Style é aplicado. Para alocar Freezable objetos, deve-se usar a segmentação indireta. Para obter mais informações sobre segmentação indireta, consulte a seção Direcionamento indireto .
Não é possível especificar um SourceName para um EventTrigger ou um Trigger.
Não é possível usar referências de recursos dinâmicos ou expressões de vinculação de dados para definir Storyboard ou valores de propriedade de animação. Isso porque tudo dentro de um Style deve ser thread-safe, e o sistema de cronometragem deve usar objetos FreezeStoryboard para torná-los thread-safe. A Storyboard não pode ser congelado se ele ou suas linhas do tempo filho contiverem referências de recursos dinâmicos ou expressões de associação de dados. Para obter mais informações sobre congelamento e outros Freezable recursos, consulte a Visão geral de objetos congeláveis.
Em XAML, você não pode declarar manipuladores de eventos para Storyboard ou eventos de animação.
Para ver um exemplo que mostra como definir um storyboard em um estilo, consulte o exemplo Animar em um estilo.
Animar num ControlTemplate
Você pode usar Storyboard objetos para definir animações em um ControlTemplate. Animar com um Storyboard num ControlTemplate é semelhante a usar um Storyboard noutro lugar, com as duas seguintes exceções:
O TargetName pode referir-se apenas a objetos filho do ControlTemplate. Se TargetName não for especificado, a animação tem como alvo o elemento ao qual a ControlTemplate é aplicada.
O SourceName para um EventTrigger ou um Trigger pode referir-se apenas a objetos filho do ControlTemplate.
Não é possível usar referências de recursos dinâmicos ou expressões de vinculação de dados para definir Storyboard ou valores de propriedade de animação. Isso porque tudo dentro de um ControlTemplate deve ser thread-safe, e o sistema de cronometragem deve usar objetos FreezeStoryboard para torná-los thread-safe. A Storyboard não pode ser congelado se ele ou suas linhas do tempo filho contiverem referências de recursos dinâmicos ou expressões de associação de dados. Para obter mais informações sobre congelamento e outros Freezable recursos, consulte a Visão geral de objetos congeláveis.
Em XAML, você não pode declarar manipuladores de eventos para Storyboard ou eventos de animação.
Para um exemplo que mostra como definir um storyboard em um ControlTemplate, veja o exemplo 'Animate in a ControlTemplate'.
Animar quando um valor de propriedade é alterado
Em estilos e modelos de controle, você pode usar objetos Trigger para iniciar um storyboard quando uma propriedade for alterada. Para obter exemplos, consulte Acionar uma animação quando um valor de propriedade é alterado e Animar em um ControlTemplate.
As animações aplicadas a objetos da propriedade Trigger comportam-se de forma mais complexa do que as animações EventTrigger ou animações iniciadas usando os métodos Storyboard. Eles "entregam" animações definidas por outros objetos Trigger, mas compõem com animações EventTrigger e acionadas por método.
Ver também
- Visão geral da animação
- Visão Geral das Técnicas de Animação de Propriedades
- Visão geral de objetos congeláveis
.NET Desktop feedback