Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
En este tema se muestra cómo usar Storyboard objetos para organizar y aplicar animaciones. Describe cómo manipular Storyboard objetos de forma interactiva y describe la sintaxis para apuntar a propiedades indirectas.
Prerrequisitos
Para comprender este tema, debe estar familiarizado con los diferentes tipos de animación y sus características básicas. Para obtener una introducción a la animación, consulta Información general sobre animaciones. También debe saber cómo usar las propiedades adjuntas. Para obtener más información sobre las propiedades adjuntas, vea Información general sobre las propiedades adjuntas.
¿Qué es un guión gráfico?
Las animaciones no son el único tipo útil de escala de tiempo. Se proporcionan otras clases de escala de tiempo para ayudarle a organizar conjuntos de escalas de tiempo y para aplicar escalas de tiempo a las propiedades. Las escalas de tiempo del contenedor derivan de la TimelineGroup clase e incluyen ParallelTimeline y Storyboard.
Un Storyboard es un tipo de línea de tiempo de contenedor que proporciona información de direccionamiento para las líneas de tiempo que contiene. Un Guión gráfico puede contener cualquier tipo de Timeline, incluyendo otras líneas de tiempo y animaciones de contenedor. Storyboard Los objetos permiten combinar escalas de tiempo que afectan a una variedad de objetos y propiedades en un único árbol de escala de tiempo, lo que facilita la organización y el control de comportamientos de tiempo complejos. Por ejemplo, supongamos que desea un botón que haga estas tres cosas.
Aumentar y cambiar de color cuando el usuario selecciona el botón.
Disminuya de tamaño y luego recupere su tamaño original al hacer clic en él.
Reducirse y desvanecerse hasta el 50% de opacidad cuando se encuentra deshabilitado.
En este caso, tienes varios conjuntos de animaciones que se aplican al mismo objeto y quieres reproducir en momentos diferentes, dependiendo del estado del botón. Storyboard Los objetos permiten organizar animaciones y aplicarlas en grupos a uno o varios objetos.
Dónde puede usar un guión gráfico
Un Storyboard se puede usar para animar las propiedades de dependencia de las clases animables (para obtener más información sobre lo que hace que una clase sea animable, consulte Información general sobre animaciones). Sin embargo, dado que el guion gráfico es una característica a nivel de marco, el objeto debe pertenecer a NameScope de un FrameworkElement o un FrameworkContentElement.
Por ejemplo, podría usar un Storyboard para hacer lo siguiente:
Animar un SolidColorBrush (elemento que no es de marco) que pinta el fondo de un botón (un tipo de FrameworkElement),
Anima un SolidColorBrush (elemento no marco) que aplica el relleno a un GeometryDrawing (elemento no marco) mostrado usando un Image (FrameworkElement).
En código, anima un SolidColorBrush declarado por una clase que también contiene un FrameworkElement, si el SolidColorBrush registró su nombre con ese FrameworkElement.
Sin embargo, no se podía usar un Storyboard para animar un SolidColorBrush que no registrara su nombre con un FrameworkElement o FrameworkContentElement, o que no se utilizara para establecer una propiedad de un FrameworkElement o FrameworkContentElement.
Cómo aplicar animaciones con un guión gráfico
Para usar un Storyboard para organizar y aplicar animaciones, agregue las animaciones como líneas de tiempo secundarias del Storyboard. La clase Storyboard proporciona las propiedades adjuntas Storyboard.TargetName y Storyboard.TargetProperty. Estas propiedades se establecen en una animación para especificar su objeto de destino y su propiedad.
Para aplicar animaciones a sus destinos, comience Storyboard usando una acción de desencadenador o un método para ello. En XAML, usas un objeto BeginStoryboard con EventTrigger, Trigger, o DataTrigger. En el código, también puede usar el método Begin.
En la siguiente tabla se muestran los diferentes lugares donde se admite cada técnica de inicio: por instancia, por estilo, plantilla de control y plantilla de datos. "Por instancia" hace referencia a la técnica de aplicar una animación o guion gráfico directamente a instancias de un objeto, en lugar de en un estilo, plantilla de control o plantilla de datos.
| Guión gráfico comienza a usar... | Por cada instancia | Estilo | Plantilla de control | Plantilla de datos | Ejemplo |
|---|---|---|---|---|---|
| BeginStoryboard y un EventTrigger | Sí | Sí | Sí | Sí | Animar una propiedad mediante un guión gráfico |
| BeginStoryboard y una propiedad Trigger | No | Sí | Sí | Sí | Desencadenar una animación cuando cambia un valor de propiedad |
| BeginStoryboard y una propiedad MultiTrigger | No | Sí | Sí | Sí | Ejemplo de clase MultiTrigger |
| BeginStoryboard y DataTrigger | No | Sí | Sí | Sí | Cómo: Desencadenar una animación cuando cambian los datos |
| BeginStoryboard y MultiDataTrigger | No | Sí | Sí | Sí | Ejemplo de clase MultiDataTrigger |
| método Begin | Sí | No | No | No | Animar una propiedad mediante un guión gráfico |
En el siguiente ejemplo se utiliza Storyboard para animar el Width de un Rectangle elemento y el Color de un SolidColorBrush utilizado para pintar dicho 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;
}
}
}
En las siguientes secciones se describen con más detalle las propiedades adjuntas de TargetName y TargetProperty.
Elementos de marco de destino, elementos de contenido de marco y elementos congelables.
En la sección anterior se mencionó que, para que una animación encuentre su objetivo, debe conocer el nombre del objetivo y la propiedad que debe animar. Especificar la propiedad que se va a animar es sencillo: simplemente configura TargetProperty con el nombre de la propiedad que se va a animar. Especifique el nombre del objeto cuya propiedad desea animar estableciendo la Storyboard.TargetName propiedad en la animación.
Precaución
Aunque puede usar la Target propiedad para enlazar directamente a un objeto como alternativa a TargetName, no se puede serializar. No hay ninguna garantía de que el Target objeto se pueda hacer referencia correctamente en XAML.
Para que la TargetName propiedad funcione, el objeto de destino debe tener un nombre. Asignar un nombre a un FrameworkElement o a un FrameworkContentElement en XAML es diferente de asignar un nombre a un objeto Freezable.
Los elementos framework son las clases que heredan de la FrameworkElement clase . Algunos ejemplos de elementos del marco de trabajo son Window, DockPanel, Buttony Rectangle. Básicamente, todas las ventanas, paneles y controles son elementos. Los elementos de contenido del marco son esas clases que heredan de la FrameworkContentElement clase . Entre los ejemplos de elementos de contenido del marco se incluyen FlowDocument y Paragraph. Si no está seguro de si un tipo es un elemento de marco o un elemento de contenido de marco, compruebe si tiene una propiedad Name. Si es así, es probable que sea un elemento de marco o un elemento de contenido de marco. Para asegurarse, compruebe la sección Jerarquía de herencia de su página de tipo.
Para habilitar el destino de un elemento de marco o un elemento de contenido de marco en XAML, estableces su Name propiedad. En el código, también debe usar el método RegisterName para registrar el nombre del elemento con el elemento para el cual ha creado un NameScope.
En el ejemplo siguiente, tomado del ejemplo anterior, se asigna al nombre MyRectangle un tipo de Rectangle llamado 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);
Una vez que tenga un nombre, puede animar una propiedad de ese 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 los tipos son esas clases que heredan de la Freezable clase . Algunos ejemplos de Freezable incluyen SolidColorBrush, RotateTransformy GradientStop.
Para habilitar el destino de un Freezable por una animación en XAML, utilizas la directiva x:Name para asignarle un nombre. En el código, se usa el RegisterName método para registrar su nombre con el elemento para el que ha creado un NameScope.
En el ejemplo siguiente se asigna un nombre a un Freezable objeto .
<SolidColorBrush x:Name="MySolidColorBrush" Color="Blue" />
SolidColorBrush mySolidColorBrush = new SolidColorBrush(Colors.Blue);
this.RegisterName("MySolidColorBrush", mySolidColorBrush);
A continuación, un objeto puede ser dirigido por una animación.
<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 los objetos usan ámbitos de nombre para resolver la TargetName propiedad . Para más información sobre los ámbitos de nombres de WPF, consulta Ámbitos de nombres XAML de WPF. Si se omite la TargetName propiedad , la animación tiene como destino el elemento en el que se define o, en el caso de los estilos, el elemento con estilo.
A veces no se puede asignar un nombre a un Freezable objeto . Por ejemplo, si se Freezable declara como un recurso o se usa para establecer un valor de propiedad en un estilo, no se puede asignar un nombre. Dado que no tiene un nombre, no se puede dirigir directamente, pero se puede apuntar indirectamente. En las secciones siguientes se describe cómo usar la segmentación indirecta.
Orientación indirecta
Hay veces que Freezable no se puede dirigir directamente a una animación, como cuando Freezable se declara como un recurso o se usa para establecer un valor de propiedad en un estilo. En estos casos, aunque no se pueda apuntar directamente, todavía puede animar el objeto Freezable. En lugar de establecer la TargetName propiedad con el nombre de Freezable, se le asigna el nombre del elemento al que Freezable pertenece. Por ejemplo, un SolidColorBrush se utiliza para establecer el Fill de un elemento rectángulo pertenece a ese rectángulo. Para animar el pincel, configurarías la animación de TargetProperty con una cadena de propiedades que comienza en la propiedad del elemento del marco o del elemento de contenido del marco donde se utilizó Freezable y termina con la propiedad Freezable a 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);
Tenga en mente que, si Freezable está congelado, se hará un clon y ese clon será animado. Cuando esto sucede, la propiedad del HasAnimatedProperties objeto original continúa devolviendo false, porque el objeto original no está realmente animado. Para obtener más información sobre la clonación, consulte la visión general de objetos Freezable.
Tenga en cuenta también que, al utilizar objetivos indirectos de propiedades, es posible apuntar a objetos que no existen. Por ejemplo, podría suponer que el Background de un botón determinado se estableció con un SolidColorBrush y tratar de animar su color, cuando de hecho se usó un LinearGradientBrush para establecer el fondo del botón. En estos casos, no se produce ninguna excepción; La animación no puede tener un efecto visible porque LinearGradientBrush no reacciona a los cambios en la Color propiedad .
En las secciones siguientes se describe la sintaxis de destino de propiedades indirectas con más detalle.
Apuntar indirectamente a una propiedad de un elemento Freezable en XAML
Para establecer como destino una propiedad de un elemento freezable en XAML, use la sintaxis siguiente.
| Sintaxis de propiedad |
|---|
ElementPropertyName.FreezablePropertyName |
Dónde
ElementPropertyName es la propiedad de la FrameworkElement que Freezable se usa para establecer y
FreezablePropertyName es la propiedad del objeto Freezable que se va a animar.
En el código siguiente se muestra cómo animar el Color de un SolidColorBrush utilizado para establecer el Fill de un elemento rectá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>
A veces, necesita dirigirse a un elemento congelable contenido en una colección o matriz.
Para tener como destino un elemento freezable contenido en una colección, use la siguiente sintaxis de ruta de acceso.
| Sintaxis de path |
|---|
ElementPropertyName.Children[CollectionIndex].FreezablePropertyName |
Donde CollectionIndex es el índice del objeto en su matriz o colección.
Por ejemplo, supongamos que un rectángulo tiene un TransformGroup recurso aplicado a su RenderTransform propiedad y desea animar una de las transformaciones que contiene.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
En el código siguiente se muestra cómo animar la Angle propiedad del RotateTransform que se muestra en el ejemplo 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>
Indirectamente tener como destino una propiedad de un elemento Freezable en el código
En el código, se crea un PropertyPath objeto . Cuando creas el PropertyPath, especificas un Path y un PathParameters.
Para crear PathParameters, cree una matriz de tipo DependencyProperty que contenga una lista de campos de identificador de propiedad de dependencia. El primer campo de identificador es para la propiedad de FrameworkElement o FrameworkContentElement que Freezable se usa para establecer. El siguiente campo de identificador representa la propiedad del destino Freezable . Piense en ella como una cadena de propiedades que conecta el Freezable al objeto FrameworkElement.
A continuación se muestra un ejemplo de una cadena de propiedades de dependencia que tiene como destino el Color de un SolidColorBrush utilizado para establecer el Fill de un elemento de rectángulo.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
También debe especificar un Path. Path es un String que indica a Path cómo interpretar su PathParameters. Usa la sintaxis siguiente.
| Sintaxis de ruta de propiedad |
|---|
(
OwnerPropertyArrayIndex).(FreezablePropertyArrayIndex) |
Dónde
OwnerPropertyArrayIndex es el índice de la matriz DependencyProperty que contiene el identificador de la propiedad del objeto FrameworkElement que se utiliza para establecer Freezable y
FreezablePropertyArrayIndex es el índice de la DependencyProperty matriz que contiene el identificador de la propiedad que se va a establecer como destino.
En el ejemplo siguiente se muestra que Path acompañaría al PathParameters definido en el ejemplo anterior.
DependencyProperty[] propertyChain =
new DependencyProperty[]
{Rectangle.FillProperty, SolidColorBrush.ColorProperty};
string thePath = "(0).(1)";
En el ejemplo siguiente se combina el código de los ejemplos anteriores para animar el Color de un SolidColorBrush objeto usado para establecer el Fill de un elemento de rectá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);
A veces, necesita dirigirse a un elemento congelable contenido en una colección o matriz. Por ejemplo, supongamos que un rectángulo tiene un TransformGroup recurso aplicado a su RenderTransform propiedad y desea animar una de las transformaciones que contiene.
<TransformGroup x:Key="MyTransformGroupResource"
x:Shared="False">
<ScaleTransform />
<RotateTransform />
</TransformGroup>
Para dirigirse a un Freezable elemento contenido en una colección, use la siguiente sintaxis de ruta de acceso.
| Sintaxis de path |
|---|
(
OwnerPropertyArrayIndex).(CollectionChildrenPropertyArrayIndex)[CollectionIndex].(FreezablePropertyArrayIndex) |
Donde CollectionIndex es el índice del objeto en su matriz o colección.
Para establecer como destino la Angle propiedad de RotateTransform, la segunda transformación de TransformGroup, usaría lo siguiente Path y 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);
En el ejemplo siguiente se muestra el código completo para animar el Angle de un RotateTransform contenido dentro de un 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);
Dirigir indirectamente con un Freezable como punto de partida
En las secciones anteriores se describe cómo establecer indirectamente un Freezable como destino comenzando con un FrameworkElement o FrameworkContentElement y creando una cadena de propiedades hasta una subpropiedad Freezable. También puede usar un Freezable como punto de partida y dirigirse indirectamente a una de sus Freezable subpropiedades. Se aplica una restricción adicional cuando se usa un Freezable como punto de partida para la segmentación indirecta: el Freezable de inicio y cada Freezable entre este y la subpropiedad a la que se apunta indirectamente no deben estar inmovilizados.
Controlar interactivamente un guión gráfico en XAML
Para iniciar un storyboard en Lenguaje de marcado extensible de aplicaciones (XAML), usa una acción desencadenante BeginStoryboard. BeginStoryboard distribuye las animaciones a los objetos y propiedades que animan e inicia el guión gráfico. (Para obtener más información sobre este proceso, consulte Información general sobre el sistema de animación y control de tiempo). Si asigna un BeginStoryboard nombre especificando su Name propiedad, lo convierte en un guión gráfico controlable. A continuación, puede controlar interactivamente el guión gráfico después de que se inicie. A continuación se muestra una lista de acciones de guion gráfico controlables que se usan con desencadenadores de eventos para controlar un guión gráfico.
PauseStoryboard: pausa el guión gráfico.
ResumeStoryboard: reanuda un guión gráfico en pausa.
SetStoryboardSpeedRatio: cambia la velocidad del guión gráfico.
SkipStoryboardToFill: Avanza un storyboard al final de su período de llenado, si tiene uno.
StopStoryboard: detiene el guión gráfico.
RemoveStoryboard: quita el guión gráfico.
En el ejemplo siguiente, las acciones de guion gráfico controlables se usan para controlar interactivamente un guión gráfico.
<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>
Control interactivo de un guión gráfico mediante código
En los ejemplos anteriores se ha mostrado cómo animar mediante acciones de desencadenador. En el código, también puede controlar un guión gráfico mediante métodos interactivos de la Storyboard clase .
Storyboard Para que un elemento se haga interactivo en el código, debe usar la sobrecarga adecuada del método del Begin guión gráfico y especificar true para que sea controlable. Consulte la Begin(FrameworkElement, Boolean) página para obtener más información.
En la siguiente lista se muestran los métodos que se pueden usar para manipular un Storyboard después de haber comenzado:
La ventaja de usar estos métodos es que no necesita crear objetos Trigger o TriggerAction; solo necesita una referencia al Storyboard controlable que desea manipular.
Nota:
Todas las acciones interactivas realizadas en un Clock y, por lo tanto, también en un Storyboard se producirán en el siguiente instante del motor de temporización que ocurrirá poco antes del siguiente renderizado. Por ejemplo, si usa el Seek método para saltar a otro punto de una animación, el valor de la propiedad no cambia al instante, sino que el valor cambia en el siguiente tic del motor de control de tiempo.
En el ejemplo siguiente se muestra cómo aplicar y controlar animaciones mediante los métodos interactivos de la Storyboard clase .
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
Crear animaciones de estilo
Puede usar Storyboard objetos para definir animaciones en un Style. Animar con un Storyboard en un Style es similar al uso de un elemento Storyboard en otro lugar, con las tres excepciones siguientes:
No se especifica un TargetName; el Storyboard siempre tiene como destino el elemento al que se aplica el Style. Para apuntar a Freezable objetos, debe usar la focalización indirecta. Para obtener más información sobre la segmentación indirecta, consulte la sección Destino indirecto .
No se puede especificar un SourceName para un EventTrigger o un Trigger.
No se pueden usar referencias de recursos dinámicos ni expresiones de enlace de datos para establecer valores de propiedad de animación en Storyboard. Esto se debe a que todo dentro de un Style debe ser seguro para subprocesos, y el sistema de control de tiempo debe FreezeStoryboard objetos para que sean seguros para subprocesos. No se puede congelar un Storyboard si sus líneas de tiempo hijas contienen referencias dinámicas de recursos o expresiones de enlace de datos. Para obtener más información sobre la congelación y otras Freezable características, consulte la Descripción general de los objetos congelables.
En XAML, no puedes declarar controladores de eventos para Storyboard o eventos de animación.
Para un ejemplo que muestra cómo definir un storyboard en un estilo, ver el ejemplo Animate en un estilo.
Animar en un ControlTemplate
Puede usar Storyboard objetos para definir animaciones en un ControlTemplate. Animar con un Storyboard en un ControlTemplate es similar al uso de un Storyboard en otro lugar, con las siguientes dos excepciones:
TargetName solo puede hacer referencia a objetos secundarios de ControlTemplate. Si no se especifica TargetName, la animación se dirige al elemento al que se aplica ControlTemplate.
El SourceName para un EventTrigger o Trigger solo puede hacer referencia a los objetos secundarios de ControlTemplate.
No se pueden usar referencias de recursos dinámicos ni expresiones de enlace de datos para establecer valores de propiedad de animación en Storyboard. Esto se debe a que todo dentro de un ControlTemplate debe ser seguro para subprocesos, y el sistema de control de tiempo debe FreezeStoryboard objetos para que sean seguros para subprocesos. No se puede congelar un Storyboard si sus líneas de tiempo hijas contienen referencias dinámicas de recursos o expresiones de enlace de datos. Para obtener más información sobre la congelación y otras Freezable características, consulte la Descripción general de los objetos congelables.
En XAML, no puedes declarar controladores de eventos para Storyboard o eventos de animación.
Para obtener un ejemplo en el que se muestra cómo definir un storyboard en ControlTemplate, vea el ejemplo Animate en un ControlTemplate.
Animar cuando se modifica el valor de una propiedad
En estilos y plantillas de control, puede usar objetos Trigger para iniciar un guión gráfico cuando cambia una propiedad. Para obtener ejemplos, vea Desencadenar una animación cuando cambia un valor de propiedad y animar en un controlTemplate.
Las animaciones aplicadas por los objetos de propiedad Trigger se comportan de forma más compleja que las animaciones EventTrigger o animaciones iniciadas mediante métodos Storyboard. Se "entregan" con animaciones definidas por otros Trigger objetos, pero se componen con EventTrigger animaciones desencadenadas por métodos y .
Consulte también
- Visión general de animación
- Introducción a las técnicas de animación de propiedades
- Introducción a los objetos Freezable
.NET Desktop feedback