API de animación

Las clases principales en la API de animación son Animator y Animation. Para utilizar las clases principales, también trabajará con la clase AnimationKeyframeSequence y AnimatedScalar o la clase AnimatedVector. Todas estas clases están en el paquete net.rim.device.api.animation.

Cree y controle las animaciones mediante la clase Animator. Invoque uno de sus métodos addAnimation(), lo que devuelve un objeto Animation. El destino de su animación debe implementar la interfaz Animatable. En la mayoría de los casos, puede utilizar tanto AnimatedScalar o AnimatedVector para representar las propiedades de Animatable del objeto que desea animar. Si no puede utilizar estas clases para representar las propiedades, también hay otras clases en el paquete net.rim.device.api.math que implementan Animatable. Si ninguna de las clases predefinidas funciona para su aplicación, puede crear un objeto de Animatable personalizado creando una clase que implemente Animatable.

Diagrama de clases de la API de animación

Clase o interfaz

Descripción

Animator

Esta clase representa el nodo raíz del conjunto de animaciones que desea gestionar. Puede invocar uno de sus métodos addAnimation() para crear una animación. Puede invocar begin() y end() para iniciar y detener la animación que haya creado.

Animation

Esta clase representa una animación y le permite gestionar la animación.

Animatable

Esta interfaz describe el conjunto de métodos que ha implementado para crear su propio objeto Animatable.

AnimatedScalar

Esta clase implementa una propiedad escalar predefinida de Animatable.

AnimatedVector

Esta clase implementa una propiedad vectorial predefinida de Animatable.

AnimationKeyframeSequence

Esta clase representa una secuencia de fotogramas clave y le permite especificar puntos de referencia en una secuencia de animación. El marco de animación interpola entre los puntos de referencia que especifique.

AnimationGroup

Esta clase representa un grupo de animaciones y le permite controlar estas animaciones como un grupo en vez de individualmente.

AnimationTrigger

Esta clase representa un objeto que puede agregar a una animación y usar posteriormente para iniciar o detener la animación.

AnimationValue

Esta clase proporciona un contenedor del valor de una propiedad de Animatable que se está animando.

AbstractAnimation

Esta clase define la funcionalidad básica para animaciones y grupos de animación.

Ejemplo de código: crear e iniciar una animación básica

El siguiente ejemplo de código no crea una animación completa. Ilustra los pasos claves necesarios para configurar una animación sencilla de un objeto vectorial de Animatable.

Para mejorar el ejemplo de código y convertirlo en una animación que funcione, debe seguir los siguientes pasos:
  • Añada código para dibujar un objeto en la pantalla en la ubicación especificada por la variable position .
  • Establezca un servicio de escucha para el motor de la animación para invocarlo cada vez que actualice la posición del objeto .
  • En respuesta a cada llamada, dibuje su objeto en la pantalla en la position actual.
 
Animator animator = new Animator(25);
AnimatedVector position = new AnimatedVector( new float[] { 0.0f, 0.0f }, 0 ); 
Animation animation = animator.addAnimationTo(
 position,
 AnimatedVector.ANIMATION_PROPERTY_VECTOR, 
 new float[] { 100.0f, 100.0f }, 
 0,
 Animation.EASINGCURVE_LINEAR, 1000L);
animation.setRepeatCount(1.0f);
animation.begin(1000L);

Fotogramas clave

Las animaciones se crean presentando una serie de imágenes lo suficientemente rápidas, de forma que el ojo humano no note una transición brusca entre las imágenes. Si no hay apenas diferencias entre las imágenes adyacentes de la serie, cualquier persona que vea la animación tendrá la sensación de estar viendo una escena uniforme que va cambiando, en vez de una serie de imágenes.

Cada imagen estática de una animación se denomina fotograma. El término fotograma proviene de la tecnología cinematográfica. Una tira de película se divide en una serie de imágenes que se separan unas de otras mediante porciones de película delgadas y sin utilizar, denominadas líneas de marco. En su conjunto, las partes sin utilizar y los bordes de la película aparecen como un marco de imagen alrededor de cada imagen individual.

Un método para crear una animación es crear cada uno de los fotogramas que desea incluir de forma individual. Este método se denomina keyframing. Keyframing le ofrece al animador un control preciso sobre la animación, pero requiere mucho trabajo. Otro método es crear sólo algunos de los fotogramas más importantes. Los fotogramas creados se denominan fotogramas clave y son miembros pivotales o complejos de la serie de imágenes.

En la animación clásica, un animador senior se puede encargar de crear los fotogramas clave y los animadores junior pueden rellenar los fotogramas intermedios. En la animación por ordenador, el animador puede especificar los fotogramas clave y el ordenador puede utilizar algoritmos de interpolación para generar los fotogramas intermedios. El proceso de interpolación se denomina tweening (intermediación).

Con la API de animación, especifica los fotogramas clave mediante la claseKeyframeSequence y el marco de animación emplea la interpolación para calcular los valores de las propiedades de Animatable de la animación entre los fotogramas clave.

Curvas de velocidad

Las curvas de velocidad son funciones que especifican la velocidad de una animación. Puede utilizarlas para hacer que las animaciones parezcan más reales sin tener que realizar cálculos físicos. Por ejemplo, cuando anima la caída de una pelota, desea que aumente la velocidad de la pelota en el momento en que está cayendo. Una curva de velocidad con aceleración crea ese efecto.

El dominio de una función de velocidad es la fracción completa de la duración total de la animación. El intervalo constituye la fracción completa requerida para la animación total. Si e(t) es una función de velocidad y la posición de un objeto de Animatable cambia de p1 a p2 durante un periodo de tiempo de d milisegundos, entonces en un tiempo intermedio, t, el objeto está en posición p = p2 -p1*e (t) +p1.

Los trazados de las curvas de velocidad le ayudan a visualizar el efecto de una curva de velocidad en una animación. El siguiente trazado utiliza un dominio normalizado de [0,1] para representar la duración total de la animación y muestra una EASINGCURVE_BOUNCE_IN curva de velocidad.

Se utilizan diferentes términos para clasificar las curvas de velocidad.

Término Definición
Aceleración Acelera la animación.
Desaceleración Ralentiza la animación.
Aceleración-desaceleración Acelera la primera mitad de la animación y ralentiza la segunda.
Desceleración-aceleración Ralentiza la primera mitad de la animación y acelera la segunda.

La API de animación admite hasta casi 50 curvas de velocidad. Si no funciona ninguna de estas curvas para su aplicación, puede especificar una curva de velocidad personalizada mediante curvas de Bézier cúbicas.

Clases predefinidas que implementan la interfaz de Animatable

Clase de Animatable

Descripción

net.rim.device.api.animation

AnimatedScalar

define un valor escalar

AnimatedVector

define un valor vectorial

net.rim.device.api.math

Vector2f

define un vector de 2 elementos de números de punto flotante

Vector3f

define un vector de 3 elementos de números de punto flotante

Vector4f

define un vector de 4 elementos de números de punto flotante

Color3f

define un color formado por los componentes rojo, verde y azul

Color4f

define un color formado por los componentes rojo, verde, azul y alfa

Quaternion4f

define un cuaternión de 4 elementos que representa la orientación de un objeto en el espacio

Transform2D

define una transformación a 2-D

Transform3D

define una transformación a 3-D

Creación de una clase personalizada que implemente la interfaz Animatable

  1. Importe las clases y las interfaces necesarias.
    import net.rim.device.api.animation.*;
  2. Cree una clase que implemente la interfaz Animatable.
    public class PositionSizeAnimatable implements Animatable
  3. Cree constantes de enteros para representar cada una de las propiedades de la clase y crear una matriz de enteros con el fin de almacenar el número de componentes de cada propiedad. Defina variables con el fin de retener los datos para todos los componentes de la clase.
    public  static final int   ANIMATION_PROPERTY_XY = 0;
    public  static final int   ANIMATION_PROPERTY_WIDTH = 1;
    public  static final int   ANIMATION_PROPERTY_HEIGHT = 2;
    public  static final int   ANIMATION_PROPERTY_COUNT = 3;
    private static final int[] ANIMATION_PROPERTY_COMPONENT_COUNTS = { 2, 1, 1 };
    public float x, y, width, height;
    
  4. Cree un constructor que acepte y establezca los valores de todos los componentes de las propiedades de Animatable.
    public MyAnimatable(float x, float y, float height, float width) 
    {
       this.x = x; 
       this.y = y;
       this.width = width;
       this.height = height;
    }
    
  5. Implemente getAnimationValue(). El marco de animación utiliza la clase AnimationValue con el fin de encapsular los valores de objetos de Animatable que esté animando. Invoque setFloat() para almacenar los valores del componente de este objeto específico de Animatable en value.
    public void getAnimationValue(int property, AnimationValue value)
    {
       switch(property) 
       {
          case ANIMATION_PROPERTY_XY:
             value.setFloat(0, this.x);
             value.setFloat(1, this.y);    
             break;
          case ANIMATION_PROPERTY_WIDTH:
             value.setFloat(0, this.width);
             break;
          case ANIMATION_PROPERTY_HEIGHT:
             value.setFloat(0, this.height);
             break;
        }
     }
    
  6. Implemente setAnimationValue(). Invoque getFloat() para recuperar los valores actualizados del componente para este objeto de Animatable de value.
    public void setAnimationValue(int property, AnimationValue value)
    {
    	switch(property) 
    	{
    	   case ANIMATION_PROPERTY_XY:
    	      this.x = value.getFloat(0);
    	      this.y = value.getFloat(1);
    	      break;
    	   case ANIMATION_PROPERTY_WIDTH:
    	      this.width = value.getFloat(0);
    	      break;
    	   case ANIMATION_PROPERTY_HEIGHT:
    	      this.height = value.getFloat(0);
    	      break;
    	 }
    }         
    
  7. Implemente getAnimationPropertyComponentCount(). En el ejemplo de código siguiente, se realiza una comprobación para asegurarse de que el parámetro property de enteros es válido. A continuación, se devuelve la cuenta almacenada en la matriz ANIMATION_PROPERTY_COMPONENT_COUNTS.
    public int getAnimationPropertyComponentCount(int property)
    {
        if (property >= 0 && property < ANIMATION_PROPERTY_COUNT)
            return ANIMATION_PROPERTY_COMPONENT_COUNTS[property];
        return 0;
    }
     }

Ejemplo de código

import net.rim.device.api.animation.*;
 public class MyAnimatable implements Animatable
 {
      public static final int ANIMATION_PROPERTY_XY = 0;
      public static final int ANIMATION_PROPERTY_WIDTH = 1;
      public static final int ANIMATION_PROPERTY_HEIGHT = 2;
      public static final int ANIMATION_PROPERTY_COUNT = 3;
      private static final int[] ANIMATION_PROPERTY_COMPONENT_COUNTS = { 2, 1, 1 };
      public float x, y, width, height;
      public MyAnimatable(float x, float y, float height, float width) 
      {
          this.x = x;
          this.y = y;
          this.width = width;
          this.height = height;
      }
      public void getAnimationValue(int property, AnimationValue value)
      {
          switch(property) 
          {
              case ANIMATION_PROPERTY_XY:
                  value.setFloat(0, this.x);
                  value.setFloat(1, this.y);
                  break;
             case ANIMATION_PROPERTY_WIDTH:
                  value.setFloat(0, this.width);
                  break;
              case ANIMATION_PROPERTY_HEIGHT:
                  value.setFloat(0, this.height);
                  break;
          }
      }
      public void setAnimationValue(int property, AnimationValue value)
      {
          switch(property) 
          {
              case ANIMATION_PROPERTY_XY:
                  this.x = value.getFloat(0);
                  this.y = value.getFloat(1);
                  break;
              case ANIMATION_PROPERTY_WIDTH:
                  this.width = value.getFloat(0);
                  break;
              case ANIMATION_PROPERTY_HEIGHT:
                  this.height = value.getFloat(0);
                  break;
          }
      }
      public int getAnimationPropertyComponentCount(int property)
      {
          if (property >= 0 && property < ANIMATION_PROPERTY_COUNT)
              return ANIMATION_PROPERTY_COMPONENT_COUNTS[property];
          return 0;
      }
 }
Tema anterior: Animación

¿Le ha resultado útil esta información? Envíenos sus comentarios.