lunes, 6 de octubre de 2008

Realizando Animaciones a DiplayObjects en flex


Jurungando entre los excelentes componentes que se encuentran en Quietly Scheming encontramos una clase muy interesante, que permite realizar camibios a las propiedades X, Y, Width, Height, Alpha, entre muchas otras, de cualquier objeto Flex cuya clase implemente la interfaz IFlexDisplayObject.

Ustedes se preguntaran, ¿Qué hay de nuevo en esto?, pero la gran utilidad esta en la manera como esta clase raliza los cambios a estas propiedades, y es que, por ejemplo, cuando queremos pasar un objeto de un width determinado a otro, la clase se encarga de realizar efecto muy estilizado y vistoso mientras realiza la transicion entre el width original y el width deseado, y asi realiza con todaslas propiedaes.


El efecto se logra aplicando una funcion exponencial al cambio de la propida, asi q a medida que se acerca mas al valor final deseado, mas lento se realiza el cambio.

Para utilizar la clase debemos definir una funcion "generateLayout" y debemos pasarsela al objeto de tipo LayourAnimato, esta funcion va a realizar los cambios a las respectivas propiedades de nuestro LayoutTarget definido en la función. Un ejemplo de funcion sería:

public function generateLayout() : void
{
layoutTarget = layoutAnimator.targetFor(displayObject);
layoutTarget.x = Number(200);
layoutTarget.y = Number(300);
layoutTarget.unscaledWidth = Number(400);
layoutTarget.unscaledHeight = Number(600);
layoutTarget.alpha = Number(0.4);
}
Una vez construida esta funcion debemos llamar al metodo invalidateLayout(true) del objeto de tipo LayoutAnimator, en ese momento se iniciará el efecto para cambiar los valores del DisplayObject de su valor actual al nuevo valor deseado.

Tambien se puede especificar que velocidad queremos para la animacion con un numero del 0 al 1, siendo 1 el valo maximo de velocidad.

Una vez terminado el efecto, la clase dispara un evento de tipo AnimationEvent.ANIMATION_COMPLETE.

El codigo completo del proyecto lo pueden encontrar aqui, y el codigo de la aplicación principal seria el siguiente:

Código
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()">
<mx:Script>
<![CDATA[

public var layoutAnimator : LayoutAnimator = new LayoutAnimator();
public var layoutTarget : LayoutTarget;

public function init() : void
{
layoutAnimator.layoutFunction = generateLayout;
}

public function generateLayout() : void
{
layoutTarget = layoutAnimator.targetFor(panel1);
layoutTarget.x = Number(txtx.value);
layoutTarget.y = Number(txty.value);
layoutTarget.unscaledWidth = Number(txtwidth.value);
layoutTarget.unscaledHeight = Number(txtheight.value);
layoutTarget.alpha = Number(txtalpha.value);
}

public function aplicarHandler() : void
{
if(animatingPicker.selected) layoutAnimator.animationSpeed = animationSpeedPicker.value;
else layoutAnimator.animationSpeed = 1;
layoutAnimator.invalidateLayout(true);
}
]]>
</mx:Script>
<mx:Label x="124" y="297" text="y"/>
<mx:Label x="124" y="269" text="x"/>
<mx:Label x="10" y="297" text="Height"/>
<mx:Label x="10" y="323" text="Alpha"/>
<mx:Label x="10" y="269" text="Width"/>
<mx:HSlider x="54" y="329" width="133" maximum="1" minimum="0" snapInterval="0.1" id="txtalpha" value="1"/>
<mx:Canvas x="10" y="10" width="458" height="249" borderStyle="solid" borderThickness="3">
<mx:Panel id="panel1" x="10" y="10" width="263" height="107" layout="absolute" cornerRadius="11" clipContent="false">
<mx:Label x="10" y="10" text="Internet Developing" height="29" fontSize="20"/>
<mx:Label x="10" y="36" text="http://internetdeveloping.blogspot.com/"/>
</mx:Panel>
</mx:Canvas>
<mx:Button x="195" y="321" label="Aplicar" click="aplicarHandler()"/>
<mx:Label x="278" y="269" text="Animation Speed"/>
<mx:NumericStepper id="animationSpeedPicker" x="386" y="267" width="58" stepSize="0.05" maximum="1" minimum="0.1" value="0.1"/>
<mx:CheckBox id="animatingPicker" x="278" y="295" label="Animating" selected="true"/>
<mx:NumericStepper id="txtheight" x="59" y="295" width="58" stepSize="1" maximum="249" minimum="10" value="107"/>
<mx:NumericStepper id="txtx" x="140" y="267" width="58" stepSize="1" maximum="450" minimum="5" value="10"/>
<mx:NumericStepper id="txty" x="140" y="295" width="58" stepSize="1" maximum="240" minimum="5" value="10"/>
<mx:NumericStepper id="txtwidth" x="58" y="267" width="58" stepSize="1" maximum="458" minimum="10" value="263"/>

</mx:Application>

Ejemplo


Continuar leyendo...

sábado, 4 de octubre de 2008

Video Tutorial Disparanto y escuchando eventos manualmente con los metodos dispatchEvent() y addEventListener()


Dado que ActionScript 3.0 es un lenguaje orientado a eventos, me parece importante profundizar un poco mas en ese tema, hasta ahora habíamos trabajado algunos ejemplos con eventos a través de mxml, pero, de esa forma, no se puede tener un verdadero control sobre los mismos, y se desperdician muchas oportunidades y potencialidades que se pueden usar cuando los eventos se trabajan desde el lado de ActionScript 3.0.

En este tutorial vamos a despachar eventos manualmente desde un botón (pueden ser despachados por cualquier objeto cuya clase implemente la interfaz IEventDispatcher) y vamos a controlar el flujo del evento despachado con las propiedades UseCapture, Bubble y los metodos addEventListener(), removeEventListener(), dispatchEvent() y stopImmediatePropagation().

Para empezar, debemos seleccionar el evento que queremos escuchar y disparar, en mi caso voy a crear un evento propio para fines didacticos y que todos aprendamos como hacerlo. Para crear un evento propio debemos crear una clase que extienda de la clase Event, y luego procedemos a crear un identificador único para el evento definiendo dentro de la clase una constante publica y estatica de tipo String con el nombre que le queremos dar al evento (Este nombre debe ser único entre todos los eventos, ya que sera el que utilizaremos cada vez que nos querramos referir al él. En el ejemplo he creado una clase MiEvento que extiende de Event y le he asignado como identificador la constante MI_EVENTO.



Luego debemos crear las funciones Handlers que van a procesar las acciones cuando el evento se dispare, en el ejemplo las funciones p1Handler, p2Handler, p3Handler, despacharEvento y usaCaptureChange().
El handler es la función que se encarga de recibir un evento y realizar cualquier accion que uno desee, el handler puede obtener la informacion contenida en el evento y utilizarla. El handler es llamado automaticamente por el Framework de Flex inmediatamente despues de que el evento que recive, es disparado.
Luego de crear los handlers debemos empezar a escuchar el evento que queremos, para hacer eso llamamos el metodo addEventListener() desde la instancia que deseemos, en el ejemplo he creado 3 Panels, cada uno de ellos escucha el mismo evento de tipo "MiEvento.MI_EVENTO".

<?xml version="1.0" encoding="utf-8"?>


public function p1Handler(e : Event) : void
{
if(para1.selected) e.stopImmediatePropagation();
p1txt.text = "event";

traceString.text += "p1 lo escuchó\n";
}

public function p2Handler(e : Event) : void
{
if(para2.selected) e.stopImmediatePropagation();
p2txt.text = "event";

traceString.text += "p2 lo escuchó\n";
}

public function p3Handler(e : Event) : void
{
if(para3.selected) e.stopImmediatePropagation();
p3txt.text = "event";

traceString.text += "p3 lo escuchó\n";
}



El metodo addEventListener() recibe dos parametros obligatorios y 3 opcionales, los dos primeros deben ser el Identificador del evento a escuchar y la funcion Handler que deseemos, de los otros tres parametros el primero es llamado useCapture y se encarga de decidir en que momento de el ciclo de vida de el evento deseamos escucharlo, si le asignamos verdadero estamos diciendo que queremos capturarlo mientras este bajando, de lo contrario le decimos que queremos capturarlo mientras esta subiendo.
Cuando un evento es despachado por un objeto de tipo DisplayObject, podemos asignarle el parametro bubbles como verdadero, con eso le estariamos diciendo que se propague desde la instancia de lo despachó subiendo hasta su mas lejano antecesor o padre en la jerarquia de instancias y luego que vuelva a bajar hasta el objeto que lo disparó. Si le asigna falso a esta propiedad entonces el evento solo podra ser escuchado por las instancias de el mismo nivel en la jerarquía.
El cuarto parametro indica la prioridad del Handler, si tenemos mas de un handler escuchando ese evento a ese nivel en la jerarquía, podemos decidir cual queremos que se dispare primero asignandole un valor mayor en la prioridad. El último parametro de todos no va a ser estudiado en este ejemplo y tiene que ver con el uso de a memoria y el garbageCollector.

Luego de agregar los listeners necesarios procedemos a despachar el evento, en este ejemplo el evento "evt" es despachado en el momento dehacer clik en botón "button1" conenido dentro del Panel 1.

Para despachar el evento realizamos una instancia llamada "evt" de la clase Evento pasandole en el contructor el identificador MiEvento.MI_EVENTO y si queremos que se propague hacia sus ascendentes con la propuedad Bubbles.

Si queremos interrumpi en cualquier momento el flujo del evento (y anteriormente seleccionamos que queriamos un lujo de tipo "blubbles" haciendo el paremetro bubbles verdadero en el constructor del evento al momento de crearlo) debemos llamar al metodo stopImmediatePropagation() en la funcion handler desde la instancia de tipo Evento que recibimos por parametro.

Es importante dejar de escuchar un evento si sabemos que ya no lo vamos a necesitar, para hacer eso debemos llamar a la funcion removeEventListener() pasandole los tres mismos primeros parametros que le pasamos a la funcion, incluso con los mismos valores, es decir, si hicimos

Bueno para terminar el ejemplo aqui les coloco el codigo fuente descargable de el proyecto el video tutorial, el codigo fuente y un ejemplo demostrarivo en funcionamiento, espero que les sirva de algo y cualquier duda o observación no duden en comentarlo en el artículo que yo las reponderé con mucho gusto:

Parte 1

Parte 2

Parte 3

Código
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="init()" width="513" height="346">
<mx:Script>
<![CDATA[

public function init() : void
{
p2.addEventListener(MiEvento.MI_EVENTO,p2Handler,usaCapturePicker.selected);
p3.addEventListener(MiEvento.MI_EVENTO,p3Handler,usaCapturePicker.selected);
p1.addEventListener(MiEvento.MI_EVENTO,p1Handler,usaCapturePicker.selected);
}

public function usaCaptureChange() : void
{
removeListeners();

p2.addEventListener(MiEvento.MI_EVENTO,p2Handler,usaCapturePicker.selected);
p3.addEventListener(MiEvento.MI_EVENTO,p3Handler,usaCapturePicker.selected);
p1.addEventListener(MiEvento.MI_EVENTO,p1Handler,usaCapturePicker.selected);
}

public function removeListeners() : void
{
p2.removeEventListener(MiEvento.MI_EVENTO,p2Handler,true);
p3.removeEventListener(MiEvento.MI_EVENTO,p3Handler,true);
p1.removeEventListener(MiEvento.MI_EVENTO,p1Handler,true);
p2.removeEventListener(MiEvento.MI_EVENTO,p2Handler,false);
p3.removeEventListener(MiEvento.MI_EVENTO,p3Handler,false);
p1.removeEventListener(MiEvento.MI_EVENTO,p1Handler,false);
}

public function borrar() : void
{
traceString.text = "";
}

public function p1Handler(e : Event) : void
{
if(para1.selected) e.stopImmediatePropagation();
p1txt.text = "event";

traceString.text += "p1 lo escuchó\n";
}

public function p2Handler(e : Event) : void
{
if(para2.selected) e.stopImmediatePropagation();
p2txt.text = "event";

traceString.text += "p2 lo escuchó\n";
}

public function p3Handler(e : Event) : void
{
if(para3.selected) e.stopImmediatePropagation();
p3txt.text = "event";

traceString.text += "p3 lo escuchó\n";
}

public function despacharEvento(e : MouseEvent) : void
{
p1txt.text = "";
p2txt.text = "";
p3txt.text = "";

var evt : Event = new Event(MiEvento.MI_EVENTO,bubblesPicker.selected);
button1.dispatchEvent(evt);

traceString.text += "Evento disparado.\n";
}
]]>
</mx:Script>

<mx:Panel x="10" y="10" width="285" height="285" layout="absolute" title="Panel 3" id="p3">
<mx:Panel x="10" y="36" width="248" height="199" layout="absolute" title="Panel 2" id="p2">
<mx:Panel x="10" y="40" width="210" height="109" layout="absolute" title="Panel 1" id="p1">
<mx:Button id="button1" x="10" y="37" label="Despachar" click="despacharEvento(event)"/>
<mx:Label x="10" y="10" text="Label" id="p1txt"/>
<mx:CheckBox id="para1" x="126" y="8" label="Para" width="54"/>
</mx:Panel>
<mx:Label x="10" y="10" text="Label" id="p2txt"/>
<mx:CheckBox id="para2" x="168" y="8" label="Para"/>
</mx:Panel>
<mx:Label x="10" y="10" text="Label" id="p3txt"/>
<mx:CheckBox id="para3" x="205" y="8" label="Para"/>
</mx:Panel>
<mx:CheckBox id="bubblesPicker" x="226" y="321" label="Bubbles" selected="true"/>
<mx:Panel x="303" y="10" width="200" height="326" layout="absolute" title="Trace">
<mx:TextArea id="traceString" x="0" y="0" width="180" height="245"/>
<mx:Button id="button0" x="58.5" y="254" label="Borrar" click="borrar()"/>
</mx:Panel>
<mx:CheckBox id="usaCapturePicker" x="10" y="321" label="UseCapture" change="usaCaptureChange()"/>
<mx:Label x="10" y="305" text="En el listener" color="#FFFFFF"/>
<mx:Label x="213" y="305" text="En el dispatch" color="#FFFFFF"/>

</mx:Application>
Ejemplo



Continuar leyendo...