Información general sobre sistemas de temporización y animación

En este tema se describe cómo el sistema de control de tiempo usa la animación y las clases Timeline y Clock para animar propiedades.

Prerrequisitos

Para entender este tema, debe poder utilizar animaciones de WPF para animar propiedades, como se describe en Información general sobre animaciones. También ayuda conocer las propiedades de dependencia; para más información, vea Información general sobre las propiedades de dependencia.

Escalas de tiempo y relojes

En Información general sobre animaciones se describe cómo un Timeline representa un segmento de tiempo, y que una animación es un tipo de Timeline que produce valores de salida. Un objeto Timeline, por sí mismo, no hace nada más que describir un segmento de tiempo. Es el objeto Clock de la escala de tiempo quien realmente hace el trabajo. Igualmente, la animación realmente no anima las propiedades: una clase de animación describe cómo se deben calcular los valores de salida, pero es el objeto Clock creado para la animación el que controla la salida de la animación y la aplica a las propiedades.

Un Clock es un tipo especial de objeto que mantiene un estado en tiempo de ejecución relacionado con el tiempo para Timeline. Proporciona tres bits de información que son esenciales para la animación y el sistema de control de tiempo: CurrentTime, CurrentProgress y CurrentState. Un Clock determina su hora actual, progreso y estado mediante el uso de los comportamientos de tiempo descritos por sus Timeline: Duration, RepeatBehavior, AutoReverse, etc.

En la mayoría de los casos, un Clock se crea automáticamente para la escala de tiempo. Al realizar la animación mediante Storyboard o mediante el método BeginAnimation, automáticamente se crean relojes para las escalas de tiempo y las animaciones y se aplican a sus propiedades de destino. También puede crear un elemento Clock explícitamente mediante el método CreateClock de Timeline. El método MediaTimeline.CreateClock crea un reloj del tipo adecuado para el Timeline en el que es llamado. Si el Timeline contiene escalas de tiempo secundarias, también crea objetos Clock para ellas. Los objetos Clock resultantes se organizan en árboles que coinciden con la estructura del árbol de objetos Timeline para el que se han creado.

Hay diferentes tipos de relojes para diferentes tipos de escalas de tiempo. En la tabla siguiente se muestran los tipos de Clock correspondientes a algunos de los diferentes tipos de Timeline.

Tipos de objetos Timeline Tipo de reloj Propósito del reloj
Animación (hereda de AnimationTimeline) AnimationClock Genera valores de salida para una propiedad de dependencia.
MediaTimeline MediaClock Procesa un archivo multimedia.
ParallelTimeline ClockGroup Agrupa y controla sus objetos Clock secundarios.
Storyboard ClockGroup Agrupa y controla sus objetos Clock secundarios.

Puede aplicar cualquier objeto AnimationClock que cree para las propiedades de dependencia compatibles mediante el método ApplyAnimationClock.

En los escenarios de rendimiento intensivo, tales como la animación de grandes números de objetos similares, la administración del uso del propio objeto Clock puede proporcionar ventajas de rendimiento.

Los relojes y el administrador de tiempo

Al animar objetos en WPF, un administrador de tiempo administra los objetos Clock que se crearon para las escalas de tiempo. El administrador de tiempo es la raíz de un árbol de objetos Clock y controla el flujo de tiempo en ese árbol. El administrador de tiempo se crea automáticamente para cada aplicación WPF y no es visible para el programador de aplicaciones. El administrador de tiempo "marca pasos" muchas veces por segundo; el número real de pasos que se producen cada segundo varía, en función de los recursos disponibles en el sistema. Durante cada uno de estos ciclos, el administrador de tiempo calcula el estado de todos los objetos ActiveClock del árbol de tiempo.

En la ilustración siguiente se muestra la relación entre el administrador de tiempo y AnimationClock, y una propiedad de dependencia animada.

Componentes del sistema de temporización y el administrador de tiempo
Animación de una propiedad

Cuando el administrador de tiempo marca un ciclo, actualiza la hora de cada ActiveClock de la aplicación. Si Clock es AnimationClock, usa el método GetCurrentValue del AnimationTimeline desde el que se creó para calcular su valor de salida actual. AnimationClock proporciona el AnimationTimeline con la hora local actual, un valor de entrada, que normalmente es el valor base de la propiedad, y un valor de destino predeterminado. Al recuperar el valor de una propiedad animada mediante el método GetValue o su descriptor de acceso CLR, obtiene la salida de su AnimationClock.

Grupos de relojes

En la sección anterior se describió cómo hay diferentes tipos de objetos Clock para los diferentes tipos de escala de tiempo. En la ilustración siguiente se muestra la relación entre el administrador de tiempo, un ClockGroup, un AnimationClock y una propiedad de dependencia animada. Se crea un ClockGroup para las escalas de tiempo que agrupan otras escalas de tiempo, como la clase Storyboard, que agrupa animaciones y otras escalas de tiempo.

Componentes del sistema de temporización con las propiedades de dependencia y administrador de tiempo
Un objeto ClockGroup

Composición

Es posible asociar varios relojes a una única propiedad, en cuyo caso cada reloj utiliza el valor de salida del reloj anterior como su valor base. En la ilustración siguiente se muestran tres objetos AnimationClock aplicados a la misma propiedad. El reloj1 utiliza el valor base de la propiedad animada como entrada y lo utiliza para generar la salida. El reloj2 toma la salida del reloj1 como entrada y lo utiliza para generar la salida. El reloj3 toma la salida del reloj2 como entrada y lo utiliza para generar la salida. Cuando varios relojes afectan simultáneamente a la misma propiedad, se dice que están en una cadena de composición.

Componentes del sistema de temporización compuestos con varias propiedades de dependencia
Una cadena de composición

Observe que, si bien se crea una relación entre la entrada y la salida de los objetos AnimationClock en la cadena de composición, sus comportamientos de tiempo no se ven afectados; los objetos Clock (incluidos los objetos AnimationClock) tienen una dependencia jerárquica de sus objetos Clock primarios.

Para aplicar varios relojes a la misma propiedad, use ComposeHandoffBehavior al aplicar una animación Storyboard, o AnimationClock.

Pasos y consolidación de eventos

Además de calcular valores de salida, el administrador de tiempo hace otras cosas a cada paso que marca: determina el estado de cada reloj y genera los eventos adecuados.

Aunque los ciclos se producen con frecuencia, pueden ocurrir muchas cosas entre ellos. Por ejemplo, un objeto Clock se podría detener, iniciar y detener de nuevo, en cuyo caso su valor CurrentState habría cambiado tres veces. En teoría, el evento CurrentStateInvalidated puede generarse varias veces en un único ciclo; sin embargo, el motor de control de tiempo consolida los eventos, de modo que cada evento CurrentStateInvalidated se pueda generar como máximo una vez por ciclo. Esto es verdadero para todos los eventos de control de tiempo: como máximo se provoca un evento de cada tipo para un objeto Clock determinado.

Cuando un Clock cambia de estado y vuelve a su estado original entre ciclos (como, por ejemplo, al cambiar de Active a Stopped y volver de nuevo a Active), se sigue produciendo el evento asociado.

Para más información acerca de los eventos de control de tiempo, vea Información general sobre eventos de control de tiempo.

Valores actuales y valores base de propiedades

Una propiedad que se pueda animar puede tener dos valores: un valor base y un valor actual. Al establecer la propiedad mediante su descriptor de acceso CLR o el método SetValue, establece su valor base. Cuando no se anima una propiedad, su valor base y su valor actual son el mismo.

Al animar la propiedad, AnimationClock establece el valor actual de la propiedad. Al recuperar el valor de la propiedad mediante su descriptor de acceso CLR o el método GetValue, se devuelve la salida de AnimationClock cuando AnimationClock es Active o Filling. Puede recuperar el valor base de la propiedad mediante el método GetAnimationBaseValue.

Vea también