Easing (facilitar) es el nombre que se usa para denominar la variación de movimiento a lo largo de un trayecto. Esta propiedad se puede encontrar en la mayoría de los programas de animación. Está relacionada con la curva de movimiento que denota una propiedad en un intervalo de tiempo.

(Either JavaScript is not active or you are using an old version of Adobe Flash Player. Please install the newest Flash Player.)


Me gustaría mencionarles que Robert Penner, actualmente ingeniero de Adobe para Flash, especializado en matemáticas, hace años desarrollo unas clases “Tween and Transition Classes” con las cuales se podían representar una amplia gama de movimientos, simplemente instanciándolas y llamando a distintos métodos. Esas clases fueron creadas para Flash MX 2004.

Lejos de tener la capacidad y la experiencia de Penner, vamos a estudiar una clase de flash (AS3) que abstrae tres métodos públicos que nos permiten mover elementos con distintos easings. Los easings también pueden estar aplicados a otras propiedades diferentes a la posición; como pueden ser el color, la escala, rotación, etc.

Easing desacelerado

Este easing es el más utilizado, los objetos parten con una velocidad, empiezan a desacelerar hasta que se detienen en un puto destino. Para lograr este efecto, la posición del clip se incrementa en porciones cada vez más pequeñas hasta llegar a detenerse en el destino indicado. Para esto, lo que hacemos es restar el destino menos la posición actual (trayectoria) y multiplicarla por un número entre 0 y 1; esto hará que nos acerquemos más lentamente al destino, sin nunca llegar a pasarlo.

clip.x+= (pos_x - clip.x) * friction;
clip.y+= (pos_y - clip.y) * friction;

En cinemática, esto equivaldría al cálculo de la aceleración. Si tomamos como partida una de las ecuaciones de movimiento “vf = vo + a·t“; y posteriormente despejáramos la aceleración, obtendríamos algo así: “a = (vf – vo) / t“, dividir el tiempo, es lo mismo que multiplicar por un valor entre 0 y 1. En la teoría, a la velocidad que trae nuestro movieclip le incrementaríamos una aceleración negativa hasta que se detenga en la posición determinada. Para nuestro caso, la velocidad estará asociada a las posición.

Esta misma ecuación se puede aplicar a cualquier propiedad, incluso alpha.. el efecto será el mismo; en vez de corregir la posición del movieclip hará lo propio con la transparencia.

Easing elástico

En el caso del easing elástico, agregamos una dificultad más, que es una constante elástica la cuál definirá la elasticidad del movimiento cuando se alcance la posición destino. La manera en que corregimos la posición del movieclip ha cambiado en relación a la de frenado que vimos anteriormente:

speedx = (speedx * elasticity) + (pos_x - clip.x) * friction;
clip.x+= speedx;
speedy = (speedy * elasticity) + (pos_y - clip.y) * friction;
clip.y+= speedy;

Hemos creado una variable speed (velocidad) para cada eje, esta velocidad será con la que corrijamos la posición del movieclip. Esta velocidad la multiplicamos por un valor entre 0 y 1, que hará que esta velocidad vaya disminuyendo; con esto nos aseguramos que el movieclip en algún momento se detenga; por otra parte le sumamos la posición final (pos_x) menos la posición actual (clip.x), presten atención que el resultado de esta resta, será cada vez menor hasta llegar a la posición final y cuando la posición del clip sobrepase el destino, el mismo será negativo; esto es lo que genera que el movieclip vuelva y se desplace a ambos lados del destino, oscilando; para que esto no ocurra y finalmente el elemento se detenga, es que lo multiplicamos por un valor también entre 0 y 1 el cuál hará las veces de fricción, haciendo que ese valor disminuya hasta hacerse 0.
Cuanto más alto sea el valor de la constante de elasticidad, o sea, cuanto más cerca de 1, mayor será la oscilación del movieclip cuando llegue al destino; por ende, más elástico será el movimiento.

Easing In/Out

Este tipo de movimiento es interesante y no tan utilizado, se trata de que el objeto acelera hasta la mitad del trayecto marcado, y una vez alcanzada la mitad, desacelera hasta el final.
Calcular la mitad del desplazamiento del objeto no será tan sencillo, ya que este desplazamiento será el vector resultante de los desplazamientos en X e Y; por tanto tengo que estar calculando todo el tiempo este vector para saber hasta donde tendré aceleración positiva y en que momento el movieclip empezará a desacelerar.
Para hacer este cálculo utilizaremos trigonometría, en dónde ese vector será la Hipotenusa resultante del cateto opuesto Y (Yf – Yo) y el cateto adyacente X (Xf – Xo). Tenemos que el Coseno del ángulo es igual al cateto adyacente sobre la hipotenusa “cos a = Y/H“, si despejo la hipotenusa me queda esto “H = Y/cos a”. El valor de Y lo obtengo, solo me resta saber cuál es el cos del ángulo; para hallar el ángulo en flash, utilizo el método Math.atan2(X,Y); pasando como parámetros el cateto opuesto y el adyacente. Esto significa que para encontrar la magnitud del vector resultante dentro de flash, puedo aplicar esta ecuación.

H = Y / Math.cos(Math.atan2(X,Y));
Pitágoras

¿Para que me sirve hallar este vector?.. bueno, para conocer cuando el movieclip llega a la mitad del vector total hallado al principio dependiendo de la posición final que indico, o sea, hasta dónde quiero que se desplace el movieclip, en el ejemplo, el movieclip se desplaza a posiciones aleatorias tanto en X como en Y.

Bueno, toda esta cháchara no es más que fundamentos teóricos de lo que veremos dentro del código.
El ejemplo que tenemos utiliza una clase EasingTools.as la cuál tiene tres métodos, EasingBrake, EasingElastic y EasingInout, que son los responsables de ejecutar los distintos tipos de movimiento sobre nuestro movieclip.
Lo que estamos haciendo es crear una instancia de la clase, y llamar a cada método, cuando lo queramos, en este caso, llamamos al método correspondiente dependiendo qué radiobutton está seleccionado.

Cada uno de ustedes puede dotar a los clips con alguno de estos movimientos, para ello deberán pasar como parámetro al elemento que quieran mover y los valores correspondientes que personalicen este movimiento; algo así:

var movercaja:EasingTools = new EasingTools();
movercaja.EasingElastic(clip,posx,posy,0.7,0.6);

Acá pueden apreciar todo el código de la clase; aquí van a encontrar los tres métodos, uno para cada tipo de movimiento:

package  {
	
	import flash.display.MovieClip;
	import flash.events.Event;
	import fl.controls.Button;
	
	public class EasingTools {
		
		public var theend:Function;

		public function EasingBrake(clip:MovieClip,posx:Number,posy:Number,friction:Number):void {
			var root = this;
			var pos_x = posx;
			var pos_y = posy;
			clip.addEventListener(Event.ENTER_FRAME,brake);
			function brake(e:Event){
				clip.x+= (pos_x - clip.x) * friction;
				clip.y+= (pos_y - clip.y) * friction;
				if(Math.round(clip.x) == Math.round(pos_x) && Math.round(clip.y) == Math.round(pos_y)){
					clip.removeEventListener(Event.ENTER_FRAME,brake);
					root.theend();
					
				}
			}
		}
		
		public function EasingElastic(clip:MovieClip,posx:Number,posy:Number,friction:Number,elasticity:Number):void {
			var root = this;
			var pos_x = posx;
			var pos_y = posy;
			var speedx = 0;
			var speedy = 0;
			clip.addEventListener(Event.ENTER_FRAME,moveelasticity);
			function moveelasticity(e:Event){
				speedx = (speedx * elasticity) + (pos_x - clip.x) * friction;
				clip.x+= speedx;
				speedy = (speedy * elasticity) + (pos_y - clip.y) * friction;
				clip.y+= speedy;
				if(Math.round(clip.x) == Math.round(pos_x) && Math.round(clip.y) == Math.round(pos_y) && Math.round(speedx) == 0 && Math.round(speedy) == 0){
					clip.x = pos_x;
					clip.y = pos_y;
					clip.removeEventListener(Event.ENTER_FRAME,moveelasticity);
					root.theend();
				}
			}
		}
		
		public function EasingInout(clip:MovieClip,px:Number,py:Number,a:Number):void{
			var root = this;
			var asc = a;
			var pinix = clip.x;
			var piniy = clip.y;
			var posx = px;
			var posy = py;
			
			var opuesto = posy - piniy;
			var adyacente = posx - pinix;
			var radianesini = Math.atan2(opuesto,adyacente);
			var distancia = Math.abs(adyacente / Math.cos(radianesini));
			
			clip.addEventListener(Event.ENTER_FRAME,moveBox);
			
			function moveBox(e:Event){
				//Calculos
				var opuestoactual = clip.y - piniy;
				var adyacenteactual = clip.x - pinix;
				var radianes = Math.atan2(opuestoactual,adyacenteactual);
				var posactual = Math.abs(adyacenteactual / Math.cos(radianes));
				if(posactual == 0){
					clip.x+= Math.cos(radianesini);
					clip.y+= Math.sin(radianesini);
				}else if(posactual < distancia/2){
					clip.x+= posactual* asc * Math.cos(radianesini);
					clip.y+= posactual * asc * Math.sin(radianesini);
				}else{
					clip.x+= (posx - clip.x) * asc;
					clip.y+= (posy - clip.y) * asc;
				}
				if(Math.round(clip.x) == posx && Math.round(clip.y) == posy) {
					clip.x = posx;
					clip.y = posy;
					clip.removeEventListener(Event.ENTER_FRAME,moveBox);
					root.theend();
				}
			}
			
		}
	}
}

Ahora veamos el código con el que manipulamos esta clase, el mismo que encontraremos en el archivo FLA:

var movercaja:EasingTools = new EasingTools();
var posx;
var posy;
var current = "elastico";

btn.addEventListener(MouseEvent.CLICK,getPosition);
function getPosition(event:MouseEvent){
	event.target.mouseEnabled = false;
	posx = Math.round(Math.random() * stage.stageWidth);
        posy = Math.round(Math.random() * stage.stageHeight);
	switch(current) {
		case "elastico" :
			movercaja.EasingElastic(auto,posx,posy,0.7,0.6);
			break;
		case "frenado" :
			movercaja.EasingBrake(auto,posx,posy,0.3);
			break;
		case "inout" :
			movercaja.EasingInout(auto,posx,posy,0.3);
			break;
		default:
			break;
	}
}
mueveauto.theend = function(){
	btn.mouseEnabled = true;
}

r1.addEventListener(MouseEvent.CLICK, setMovement);
r2.addEventListener(MouseEvent.CLICK, setMovement);
r3.addEventListener(MouseEvent.CLICK, setMovement);
function setMovement(event:MouseEvent){
	current = event.currentTarget.value;
}

Básicamente podemos observar, que cada vez que hacemos click en un radiobutton, dejamos guardado el nombre del tipo de movimiento (ej: elastico) en la variable “current”; para que posteriormente cuando hagamos click en el botón “Mover” del escenario, se refleje ese tipo de movimiento en la cajita. Mientras la cajita se mueve, inhabilitamos el botón “Mover”, hasta que la misma se detiene y la propia clase se encarga de ejecutar la función “theend” para que desde el flash, podamos referenciarla y asignarle la acción de que vuelva a dejar activo el botón.

Espero les haya resultado útil este artículo y puedan implementar este aprendizaje en vuestras animaciones.

Descargar los archivos

¡Hasta pronto!

Categoría: Multimedia, Web

Publicado por: negro

Entradas más populares

Dejar una respuesta

XHTML: Tu pudes usar estas etiquetas: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>