Ejemplo de objeto de visualización: SpriteArranger

Flash Player 9 y posterior, Adobe AIR 1.0 y posterior

La aplicación de ejemplo SpriteArranger se basa en la aplicación de ejemplo de formas geométricas que se describe por separado en Aprendizaje de ActionScript 3.0 .

La aplicación de ejemplo SpriteArranger ilustra diversos conceptos relacionados con los objetos de visualización:

  • Ampliación de las clases de objetos de visualización

  • Añadir objetos a la lista de visualización

  • Organización en capas de los objetos de visualización y utilización de contenedores de objetos de visualización

  • Respuesta a eventos de objetos de visualización

  • Uso de propiedades y métodos de objetos de visualización

Para obtener los archivos de la aplicación de este ejemplo, consulte www.adobe.com/go/learn_programmingAS3samples_flash_es . Los archivos de la aplicación SpriteArranger se encuentran en la carpeta Examples/SpriteArranger. La aplicación consta de los siguientes archivos:

Archivo

Descripción

SpriteArranger.mxml

o

SpriteArranger.fla

El archivo de aplicación principal en Flash (FLA) o Flex (MXML).

com/example/programmingas3/SpriteArranger/CircleSprite.as

Una clase que define un tipo de objeto Sprite que representa un círculo en pantalla.

com/example/programmingas3/SpriteArranger/DrawingCanvas.as

Una clase que define el lienzo, que es un contenedor de objeto de visualización que contiene objetos GeometricSprite.

com/example/programmingas3/SpriteArranger/SquareSprite.as

Una clase que define un tipo de objeto Sprite que representa un cuadrado en pantalla.

com/example/programmingas3/SpriteArranger/TriangleSprite.as

Una clase que define un tipo de objeto Sprite que representa un triángulo en pantalla.

com/example/programmingas3/SpriteArranger/GeometricSprite.as

Una clase que amplía el objeto Sprite y que se usa para definir una forma en pantalla. CircleSprite, SquareSprite y TriangleSprite amplían esta clase.

com/example/programmingas3/geometricshapes/IGeometricShape.as

La interfaz base que define los métodos que implementarán todas las clases de formas geométricas.

com/example/programmingas3/geometricshapes/IPolygon.as

Una interfaz que define los métodos que implementarán las clases de formas geométricas que tienen varios lados.

com/example/programmingas3/geometricshapes/RegularPolygon.as

Un tipo de forma geométrica que tiene lados de igual longitud, simétricamente ubicados alrededor del centro de la forma.

com/example/programmingas3/geometricshapes/Circle.as

Un tipo de forma geométrica que define un círculo.

com/example/programmingas3/geometricshapes/EquilateralTriangle.as

Una subclase de RegularPolygon que define un triángulo con todos los lados de la misma longitud.

com/example/programmingas3/geometricshapes/Square.as

Una subclase de RegularPolygon que define un rectángulo con los cuatro lados de la misma longitud.

com/example/programmingas3/geometricshapes/GeometricShapeFactory.as

Una clase que contiene un "método de fábrica" para crear formas a partir de un tipo y tamaño de forma.

Definición de las clases de SpriteArranger

La aplicación SpriteArranger permite al usuario añadir varios objetos de visualización al "lienzo" en pantalla.

La clase DrawingCanvas define un área de dibujo, un tipo de contenedor de objeto de visualización, en el que el usuario puede añadir formas en pantalla. Estas formas en pantalla son instancias de una de las subclases de la clase GeometricSprite.

La clase DrawingCanvas

En Flex, todos los objetos de visualización secundarios agregados a un objeto Container deben ser de una clase que descienda de la clase mx.core.UIComponent. Esta aplicación añade una instancia de la clase DrawingCanvas como elemento secundario de un objeto mx.containers.VBox, tal y como se define en el código MXML del archivo SpriteArranger.mxml. Esta herencia se define en la declaración de la clase DrawingCanvas del siguiente modo:

public class DrawingCanvas extends UIComponent

La clase UIComponent hereda de las clases DisplayObject, DisplayObjectContainer y Sprite y el código de la clase DrawingCanvas emplea métodos y propiedades para estas clases.

La clase DrawingCanvas amplía la clase Sprite y su herencia se define en la declaración de la clase DrawingCanvas de la manera siguiente:

public class DrawingCanvas extends Sprite

La clase Sprite es una subclase de las clases DisplayObjectContainer y DisplayObject, y la clase DrawingCanvas utiliza los métodos y las propiedades de dichas clases.

El método constructor DrawingCanvas() configura un objeto Rectangle, bounds , que se utiliza para dibujar el contorno del lienzo. A continuación, llama al método initCanvas() , del siguiente modo:

this.bounds = new Rectangle(0, 0, w, h); 
initCanvas(fillColor, lineColor);

Tal y como se muestra en el ejemplo siguiente, el método initCanvas() define diversas propiedades del objeto DrawingCanvas que se pasaron como argumentos a la función constructora:

this.lineColor = lineColor; 
this.fillColor = fillColor; 
this.width = 500; 
this.height = 200;

El método initCanvas() llama entonces al método drawBounds() , que dibuja el lienzo a través de la propiedad graphics de DrawingCanvas. La propiedad graphics se hereda de la clase Shape.

this.graphics.clear();         
this.graphics.lineStyle(1.0, this.lineColor, 1.0); 
this.graphics.beginFill(this.fillColor, 1.0); 
this.graphics.drawRect(bounds.left - 1,  
                        bounds.top - 1,  
                        bounds.width + 2, 
                        bounds.height + 2); 
this.graphics.endFill();

Los siguientes métodos adicionales de la clase DrawingCanvas se llaman en función de las interacciones del usuario con la aplicación:

La clase GeometricSprite y sus subclases

Cada objeto de visualización que puede añadir el usuario al lienzo es una instancia de una de las siguientes subclases de la clase GeometricSprite:

  • CircleSprite

  • SquareSprite

  • TriangleSprite

La clase GeometricSprite amplía la clase flash.display.Sprite:

public class GeometricSprite extends Sprite

La clase GeometricSprite incluye varias propiedades comunes para todos los objetos GeometricSprite. Estas propiedades se definen en la función constructora según los parámetros pasados a la función. Por ejemplo:

this.size = size; 
this.lineColor = lColor; 
this.fillColor = fColor;

La propiedad geometricShape de la clase GeometricSprite define una interfaz IGeometricShape, que define las propiedades matemáticas de la forma, pero no las propiedades visuales. Las clases que implementan la interfaz IGeometricShape se definen en la aplicación de ejemplo GeometricShapes en Aprendizaje de ActionScript 3.0 .

La clase GeometricSprite define el método drawShape() , que se refina en las definiciones de sustitución de cada una de las subclases de GeometricSprite. Para obtener más información, consulte la siguiente sección "Añadir objetos de visualización al lienzo".

La clase GeometricSprite también proporciona los siguientes métodos:

Añadir objetos de visualización al lienzo

Cuando el usuario hace clic en el botón Añadir forma, la aplicación llama al método addShape() de la clase DrawingCanvas. Crea una instancia de una nueva clase GeometricSprite mediante una llamada a la función constructora adecuada de una de las subclases de GeometricSprite, como se muestra en el siguiente ejemplo:

public function addShape(shapeName:String, len:Number):void 
{ 
    var newShape:GeometricSprite; 
    switch (shapeName) 
    { 
        case "Triangle": 
            newShape = new TriangleSprite(len); 
            break; 
 
        case "Square": 
            newShape = new SquareSprite(len); 
            break; 
 
        case "Circle": 
            newShape = new CircleSprite(len); 
            break; 
    } 
    newShape.alpha = 0.8; 
    this.addChild(newShape); 
}

Cada método constructor llama al método drawShape() , que utiliza la propiedad graphics de la clase (heredada de la clase Sprite) para dibujar el gráfico vectorial adecuado. Por ejemplo, el método drawShape() de la clase CircleSprite incluye el siguiente código:

this.graphics.clear(); 
this.graphics.lineStyle(1.0, this.lineColor, 1.0); 
this.graphics.beginFill(this.fillColor, 1.0); 
var radius:Number = this.size / 2; 
this.graphics.drawCircle(radius, radius, radius);

La penúltima línea de la función addShape() define la propiedad alpha del objeto de visualización (heredada de la clase DisplayObject), de forma que cada objeto de visualización que se añade al lienzo es ligeramente transparente, lo que permite que el usuario vea los objetos que hay detrás.

La línea final del método addChild() añade el nuevo objeto de visualización a la lista de elementos secundarios de la instancia de la clase DrawingCanvas, que ya se encuentra en la lista de visualización. Como resultado, el nuevo objeto de visualización aparece en el escenario.

La interfaz de la aplicación incluye dos campos de texto: selectedSpriteTxt y outputTxt . Las propiedades de texto de estos campos se actualizan con la información relativa a los objetos GeometricSprite que se han añadido al lienzo o que ha seleccionado el usuario. La clase GeometricSprite gestiona esta tarea de notificación de información mediante la sustitución del método toString() , del siguiente modo:

public override function toString():String 
{ 
    return this.shapeType + " of size " + this.size + " at " + this.x + ", " + this.y; 
}

La propiedad shapeType se establece en el valor adecuado en el método constructor de cada subclase de GeometricSprite. Por ejemplo, el método toString() podría devolver el siguiente valor de una instancia de CircleSprite recién añadida a la instancia de DrawingCanvas:

Circle of size 50 at 0, 0

El método describeChildren() de la clase DrawingCanvas reproduce indefinidamente la lista de elementos secundarios del lienzo, utilizando la propiedad numChildren (heredada de la clase DisplayObjectContainer) para definir el límite del bucle for . Genera una cadena con el valor de cada elemento secundario, del siguiente modo:

var desc:String = ""; 
var child:DisplayObject; 
for (var i:int=0; i < this.numChildren; i++) 
{ 
child = this.getChildAt(i); 
desc += i + ": " + child + '\n'; 
}

La cadena resultante se utiliza para establecer la propiedad text del campo de texto outputTxt .

Selección mediante clic y arrastre de objetos de visualización

Cuando el usuario hace clic en una instancia de GeometricSprite, la aplicación llama al controlador de eventos onMouseDown() . Como se muestra a continuación, se define este controlador de eventos para detectar los eventos de clic del ratón en la función constructora de la clase GeometricSprite:

this.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);

A continuación, el método onMouseDown() llama al método showSelected() del objeto GeometricSprite. Si es la primera vez que se ha llamado a este método en el objeto, el método crea un nuevo objeto Shape denominado selectionIndicator y utiliza la propiedad graphics del objeto Shape para dibujar un rectángulo de resaltado rojo, del siguiente modo:

this.selectionIndicator = new Shape(); 
this.selectionIndicator.graphics.lineStyle(1.0, 0xFF0000, 1.0); 
this.selectionIndicator.graphics.drawRect(-1, -1, this.size + 1, this.size + 1); 
this.addChild(this.selectionIndicator);

Si no es la primera vez que se llama al método onMouseDown() , el método simplemente establece la propiedad visible del objeto Shape selectionIndicator (heredada de la clase DisplayObject), del siguiente modo:

this.selectionIndicator.visible = true;

El método hideSelected() oculta el objeto Shape selectionIndicator del objeto seleccionado previamente estableciendo su propiedad visible en false .

El método del controlador de eventos onMouseDown() también llama al método startDrag() (heredado de la clase Sprite), que incluye el siguiente código:

var boundsRect:Rectangle = this.parent.getRect(this.parent); 
boundsRect.width -= this.size; 
boundsRect.height -= this.size; 
this.startDrag(false, boundsRect);

De esta forma, el usuario puede arrastrar el objeto seleccionado por el lienzo, dentro de los límites definidos por el rectángulo boundsRect .

Cuando el usuario suelta el botón del ratón, se distribuye el evento mouseUp. El método constructor de DrawingCanvas configura el siguiente detector de eventos:

this.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);

Este detector de eventos se define en el objeto DrawingCanvas y no en cada uno de los objetos GeometricSprite. El motivo de ello es que, al arrastrar el objeto GeometricSprite, este podría acabar detrás de otro objeto de visualización (otro objeto GeometricSprite) al soltar el botón del ratón. El objeto de visualización en primer plano recibiría el evento de soltar el ratón pero no así el objeto de visualización que arrastra el usuario. Al añadir el detector al objeto DrawingCanvas, se garantiza un control perpetuo del evento.

El método onMouseUp() llama al método onMouseUp() del objeto GeometricSprite, que a su vez llama al método stopDrag() del objeto GeometricSprite.

Reorganización de las capas de los objetos de visualización

La interfaz de usuario de la aplicación incluye botones Move Back, Move Down, Move Up y Move to Front para mover atrás, abajo, arriba y al frente, respectivamente. Cuando el usuario hace clic en uno de estos botones, la aplicación llama al método correspondiente de la clase DrawingCanvas: moveToBack() , moveDown() , moveUp() o moveToFront() . Por ejemplo, el método moveToBack() incluye el siguiente código:

public function moveToBack(shape:GeometricSprite):void 
{ 
    var index:int = this.getChildIndex(shape); 
    if (index > 0) 
    { 
        this.setChildIndex(shape, 0); 
    } 
}

El método utiliza el método setChildIndex() (heredado de la clase DisplayObjectContainer) para colocar el objeto de visualización en la posición de índice 0 en la lista de elementos secundarios de la instancia de DrawingCanvas ( this ).

El método moveDown() funciona de forma similar, excepto en que reduce en 1 la posición de índice del objeto de visualización en la lista de elementos secundarios de la instancia de DrawingCanvas:

public function moveDown(shape:GeometricSprite):void 
{ 
    var index:int = this.getChildIndex(shape); 
    if (index > 0) 
    { 
        this.setChildIndex(shape, index - 1); 
    } 
}

Los métodos moveUp() y moveToFront() funcionan de modo similar a los métodos moveToBack() y moveDown() .