Esempio di filtraggio degli oggetti di visualizzazione: Pannello dei filtri

Flash Player 9 e versioni successive, Adobe AIR 1.0 e versioni successive

Il pannello dei filtri è un'interfaccia utente che ha lo scopo di applicare diversi filtri a immagini e altri contenuti visivi e di vedere il codice risultante da utilizzare per generare lo stesso effetto in ActionScript. Oltre a fornire uno strumento per la sperimentazione con i filtri, questa applicazione mostra le seguenti tecniche:

  • Creazione di istanze di vari filtri

  • Applicazione di diversi filtri per visualizzare un oggetto

Per ottenere i file dell'applicazione per questo esempio, visitate la pagina www.adobe.com/go/learn_programmingAS3samples_flash_it . I file di applicazione del pannello dei filtri si trovano nella cartella Samples/FilterWorkbench. L'applicazione è composta dai seguenti file:

File

Descrizione

com/example/programmingas3/filterWorkbench/FilterWorkbenchController.as

Classe contenente le principali funzioni dell'applicazione, tra cui quella che permette di cambiare i contenuti sui quali i filtri vengono applicati e quella che permette l'applicazione del filtro al contenuto.

com/example/programmingas3/filterWorkbench/IFilterFactory.as

Interfaccia che definisce i metodi comuni implementati da ciascuna classe di filter factory. Questa interfaccia definisce le funzioni comuni che la classe FilterWorkbenchController utilizza per interagire con le singole classi filter factory.

nella cartella com/example/programmingas3/filterWorkbench/:

BevelFactory.as

BlurFactory.as

ColorMatrixFactory.as

ConvolutionFactory.as

DropShadowFactory.as

GlowFactory.as

GradientBevelFactory.as

GradientGlowFactory.as

Gruppo di classi, ognuna delle quali implementa l'interfaccia IFilterFactory. Ognuna di queste classi fornisce le funzioni per la creazione e l'impostazione dei valori di un singolo tipo di filtro. I pannelli di proprietà del filtro nell'applicazione utilizzano queste classi factory per creare istanze dei loro filtri di riferimento che la classe FilterWorkbenchController recupera e applica al contenuto immagine.

com/example/programmingas3/filterWorkbench/IFilterPanel.as

Interfaccia che definisce i metodi comuni implementati dalle classi che definiscono i pannelli dell'interfaccia utente utilizzati per manipolare i valori dei filtri nell'applicazione.

com/example/programmingas3/filterWorkbench/ColorStringFormatter.as

Classe di utilità che include un metodo per convertire un valore numerico di colore in un formato stringa esadecimale

com/example/programmingas3/filterWorkbench/GradientColor.as

Classe che funge da oggetto valore, combinando in un singolo oggetto i tre valori (colore, alfa e proporzioni) che sono associati ad ogni colore del GradientBevelFilter e del GradientGlowFilter

Interfaccia utente (Flex)

FilterWorkbench.mxml

File principale per la definizione dell'interfaccia utente dell'applicazione.

flexapp/FilterWorkbench.as

Classe che fornisce le funzioni per l'applicazione principale dell'interfaccia utente; questa classe viene utilizzata come classe code-behind per il file dell'applicazione MXML.

Nella cartella flexapp/filterPanels:

BevelPanel.mxml

BlurPanel.mxml

ColorMatrixPanel.mxml

ConvolutionPanel.mxml

DropShadowPanel.mxml

GlowPanel.mxml

GradientBevelPanel.mxml

GradientGlowPanel.mxml

Gruppo di componenti MXML che fornisce le funzioni per i pannelli destinati all'impostazione delle opzioni dei vari filtri.

flexapp/ImageContainer.as

Oggetto di visualizzazione che funge da contenitore per l'immagine caricata sullo schermo

flexapp/controls/BGColorCellRenderer.as

Renderer di cella personalizzato utilizzato per modificare il colore di sfondo di una cella nel componente DataGrid

flexapp/controls/QualityComboBox.as

Controllo personalizzato che definisce una casella combinata che può essere utilizzata per l'impostazione Qualità in diversi pannelli di filtro.

flexapp/controls/TypeComboBox.as

Controllo personalizzato che definisce una casella combinata che può essere utilizzata per l'impostazione Tipo in diversi pannelli di filtro.

Interfaccia utente (Flash)

FilterWorkbench.fla

File principale per la definizione dell'interfaccia utente dell'applicazione.

flashapp/FilterWorkbench.as

Classe che fornisce le funzioni per l'applicazione principale dell'interfaccia utente; questa classe viene utilizzata come classe di documento per il file dell'applicazione FLA.

Nella cartella flashapp/filterPanels:

BevelPanel.as

BlurPanel.as

ColorMatrixPanel.as

ConvolutionPanel.as

DropShadowPanel.as

GlowPanel.as

GradientBevelPanel.as

GradientGlowPanel.as

Gruppo di classi che fornisce le funzioni per i pannelli destinati all'impostazione delle opzioni dei vari filtri.

Per ogni classe è inoltre presente un simbolo MovieClip nella libreria del file dell'applicazione FLA principale, il cui nome coincide con il nome della classe (ad esempio il simbolo “BlurPanel” è collegato alla classe definita in BlurPanel.as). I componenti dell'interfaccia utente sono posizionati e nominati all'interno di questi simboli.

flashapp/ImageContainer.as

Oggetto di visualizzazione che funge da contenitore per l'immagine caricata sullo schermo

flashapp/BGColorCellRenderer.as

Renderer di cella personalizzato utilizzato per modificare il colore di sfondo di una cella nel componente DataGrid

flashapp/ButtonCellRenderer.as

Renderer di cella personalizzato utilizzato per includere un componente pulsante in una cella del componente DataGrid

Contenuto dell'immagine filtrata

com/example/programmingas3/filterWorkbench/ImageType.as

Questa classe funge da oggetto value contenente il tipo e l'URL di un singolo file di immagine che l'applicazione carica e su cui quale applica i filtri. Questa classe comprende anche un set di costanti che rappresentano i file di immagine disponibili.

images/sampleAnimation.swf,

images/sampleImage1.jpg,

images/sampleImage2.jpg

Immagini e altri contenuti visivi sui quali applicare i filtri all'interno dell'applicazione.

Esperimenti con i filtri ActionScript

L'applicazione Pannello dei filtri è progettata per dare la possibilità di sperimentare vari effetti di filtro e generare il relativo codice ActionScript. L'applicazione permette di selezionare tre diversi file con contenuto visivo, comprese immagini bitmap e animazioni create da Flash, e di applicare otto diversi filtri ActionScript alle immagini selezionate sia singolarmente che combinati tra loro. L'applicazione comprende i seguenti filtri:

  • Smussatura (flash.filters.BevelFilter)

  • Sfocatura (flash.filters.BlurFilter)

  • Matrice colore (flash.filters.ColorMatrixFilter)

  • Convoluzione (flash.filters.ConvolutionFilter)

  • Ombra esterna (flash.filters.DropShadowFilter)

  • Bagliore (flash.filters.GlowFilter)

  • Smussatura con gradiente (flash.filters.GradientBevelFilter)

  • Bagliore con gradiente (flash.filters.GradientGlowFilter)

Dopo che l'utente ha selezionato un'immagine e un filtro da applicare, l'applicazione visualizza un pannello per l'impostazione delle proprietà specifiche del filtro selezionato. L'immagine seguente, ad esempio, mostra l'applicazione con il filtro Smussatura selezionato:

L'immagine di anteprima si aggiorna in tempo reale man mano che l'utente modifica le proprietà del filtro. L'utente ha anche la possibilità di applicare diversi filtri personalizzandone uno, facendo clic sul pulsante Applica, poi personalizzandone un'altro, facendo nuovamente clic su Applica, e così via.

Nei pannelli di filtro dell'applicazione sono presenti alcune caratteristiche e limitazioni:

  • Il filtro matrice colore include un gruppo di controlli per manipolare direttamente le proprietà comuni dell'immagine tra cui la luminosità, il contrasto, la saturazione e la tonalità. Inoltre, è possibile personalizzare i valori della matrice colore.

  • Il filtro convoluzione, disponibile solo mediante ActionScript, permette di utilizzare sia un gruppo di valori di matrice comuni esistenti, che di personalizzare tali valori. Tuttavia, mentre la classe ConvolutionFilter accetta matrici di qualsiasi dimensione, l'applicazione Pannello dei filtri utilizza una matrice 3 x 3 fissa, corrispondente alla dimensione di filtro maggiormente utilizzata.

  • Il filtro mappa di spostamento e il filtro shader, disponibili solamente in ActionScript, non sono disponibili nell'applicazione Pannello dei filtri.

Creazione di istanze di filtro

L'applicazione Pannello dei filtri comprende un gruppo di classi: una per ognuno dei filtri disponibili; queste classi vengono utilizzate dai singoli pannelli per creare i filtri. Quando un utente seleziona un filtro, il codice ActionScript associato al pannello del filtro crea un'istanza corrispondente alla classe filter factory appropriata (queste classi vengono dette classi factory perché il loro scopo è quello di creare istanze di altri oggetti, proprio come una fabbrica crea singoli prodotti).

Ogni qualvolta l'utente cambia un valore di proprietà nel pannello, il codice del pannello chiama il metodo appropriato nella classe factory. Ogni classe factory comprende metodi specifici che il pannello utilizza per creare l'istanza appropriata per il filtro. Se, ad esempio, l'utente seleziona il filtro Sfocatura, l'applicazione crea l'istanza BlurFactory. La classe BlurFactory include un metodo modifyFilter() che accetta tre parametri: blurX , blurY e quality , che vengono utilizzati insieme per creare l'istanza BlurFilter desiderata:

private var _filter:BlurFilter; 
 
public function modifyFilter(blurX:Number = 4, blurY:Number = 4, quality:int = 1):void 
{ 
    _filter = new BlurFilter(blurX, blurY, quality); 
    dispatchEvent(new Event(Event.CHANGE)); 
}

Se invece l'utente seleziona il filtro Convoluzione, poiché questo filtro è molto più flessibile le proprietà da controllare sono molte di più. Nella classe relativa a questo filtro chiamata ConvolutionFactory, quando l'utente seleziona un diverso valore sul pannello del filtro viene chiamato il seguente codice:

private var _filter:ConvolutionFilter; 
 
public function modifyFilter(matrixX:Number = 0,  
                                                matrixY:Number = 0,  
                                                matrix:Array = null,  
                                                divisor:Number = 1.0,  
                                                bias:Number = 0.0,  
                                                preserveAlpha:Boolean = true,  
                                                clamp:Boolean = true,  
                                                color:uint = 0,  
                                                alpha:Number = 0.0):void 
{ 
    _filter = new ConvolutionFilter(matrixX, matrixY, matrix, divisor, bias, preserveAlpha, clamp, color, alpha); 
    dispatchEvent(new Event(Event.CHANGE)); 
}

Notate che ogni volta che i valori del filtro vengono cambiati, l'oggetto factory invia un evento Event.CHANGE per notificare ai listener che i valori del filtro sono cambiati. La classe FilterWorkbenchController, il cui compito è quello di applicare i filtri ai contenuti filtrati, “ascolta” tali eventi per verificare quando è necessario recuperare una nuova copia del filtro e applicarlo nuovamente al contenuto filtrato.

La classe FilterWorkbenchController non ha bisogno di conoscere i dettagli specifici di ogni classe filter factory: deve solo ricevere notifica del cambiamento dei parametri del filtro ed essere in grado di accedere a una copia del filtro. Per fare questo, l'applicazione include un'interfaccia, IFilterFactory, che definisce il comportamento che una classe filter factory deve assumere in modo che l'istanza dell'applicazione FilterWorkbenchController possa svolgere questo compito. IFilterFactory definisce il metodo getFilter() che viene usato nella classe FilterWorkbenchController:

function getFilter():BitmapFilter;

Notate che la definizione del metodo di interfaccia getFilter() restituisce un'istanza BitmapFilter e non uno specifico tipo di filtro. La classe BitmapFilter non definisce uno specifico tipo di filtro. BitmapFilter è, piuttosto, una classe base sulla quale tutte le classi dei filtri sono costruite. Ogni classe filter factory definisce una specifica implementazione del metodo getFilter() in cui restituisce un riferimento all'oggetto filtro che ha costruito. Di seguito viene riportata, a scopo di esempio, una versione abbreviata del codice sorgente della classe ConvolutionFactory:

public class ConvolutionFactory extends EventDispatcher implements IFilterFactory 
{ 
    // ------- Private vars ------- 
    private var _filter:ConvolutionFilter; 
    ... 
    // ------- IFilterFactory implementation ------- 
    public function getFilter():BitmapFilter 
    { 
        return _filter; 
    } 
    ... 
}

Nell'implementazione della classe ConvolutionFactory del metodo getFilter() , viene restituita un'istanza ConvolutionFilter, sebbene gli oggetti che chiamano getFilter() non ne siano necessariamente a conoscenza: secondo la definizione del metodo getFilter() seguito da ConvolutionFactory, esso deve restituire qualsiasi istanza BitmapFilter, la quale a sua volta può essere un'istanza di qualsiasi classe del filtro ActionScript.

Applicazione dei filtri agli oggetti di visualizzazione

Come illustrato in precedenza, l'applicazione Pannello dei filtri utilizza un'istanza della classe FilterWorkbenchController (da qui in avanti indicata come “istanza di controllo”), che ha il vero e proprio compito di applicare i filtri agli oggetti visivi selezionati. Affinché l'istanza di controllo possa applicare un filtro, deve sapere a quale immagine o contenuto visivo il filtro deve essere applicato. Quando l'utente seleziona un'immagine, l'applicazione chiama il metodo setFilterTarget() nella classe FilterWorkbenchController, passando una delle costanti definite nella classe ImageType:

public function setFilterTarget(targetType:ImageType):void 
{ 
    ... 
    _loader = new Loader(); 
    ... 
    _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, targetLoadComplete); 
    ... 
}

Utilizzando questa informazione, l'istanza di controllo carica il file selezionato memorizzandolo in una variabile di istanza chiamata _currentTarget al momento del caricamento:

private var _currentTarget:DisplayObject; 
 
private function targetLoadComplete(event:Event):void 
{ 
    ... 
    _currentTarget = _loader.content; 
    ... 
}

Quando l'utente seleziona un filtro, l'applicazione chiama il metodo dell'istanza di controllo setFilter() assegnando all'istanza di controllo un riferimento all'oggetto filter factory corrispondente, il quale memorizza una variabile di istanza denominata _filterFactory .

private var _filterFactory:IFilterFactory; 
 
public function setFilter(factory:IFilterFactory):void 
{ 
    ... 
     
    _filterFactory = factory; 
    _filterFactory.addEventListener(Event.CHANGE, filterChange); 
}

Notate che, come descritto in precedenza, l'istanza di controllo non conosce il tipo di dati specifici dell'istanza filter factory assegnata; sa solamente che l'oggetto implementa l'istanza IFilterFactory e questo vuol dire che dispone di un metodo getFilter() e che invia un evento change ( Event.CHANGE ) quando il filtro viene modificato.

Quando l'utente modifica le proprietà di un filtro nel pannello, l'istanza di controllo rileva che il filtro è stato modificato tramite l'evento change della filter factory, che chiama il metodo filterChange() dell'istanza di controllo. Questo metodo, a sua volta, chiama il metodo applyTemporaryFilter() :

private function filterChange(event:Event):void 
{ 
    applyTemporaryFilter(); 
} 
 
private function applyTemporaryFilter():void 
{ 
    var currentFilter:BitmapFilter = _filterFactory.getFilter(); 
     
    // Add the current filter to the set temporarily 
    _currentFilters.push(currentFilter); 
     
    // Refresh the filter set of the filter target 
    _currentTarget.filters = _currentFilters; 
     
    // Remove the current filter from the set 
    // (This doesn't remove it from the filter target, since  
    // the target uses a copy of the filters array internally.) 
    _currentFilters.pop(); 
}

L'applicazione del filtro all'oggetto di visualizzazione avviene all'interno del metodo applyTemporaryFilter() . Per prima cosa l'istanza di controllo recupera un riferimento all'oggetto filtro chiamando il metodo getFilter() della filter factory.

var currentFilter:BitmapFilter = _filterFactory.getFilter();

L'istanza di controllo dispone di una variabile di istanza Array denominata _currentFilters , nella quale memorizza tutti i filtri che sono stati applicati all'oggetto di visualizzazione. Il passaggio successivo consiste nell'aggiungere il filtro appena aggiornato all'array:

_currentFilters.push(currentFilter);

Successivamente il codice assegna l'array dei filtri alla proprietà filters dell'oggetto di visualizzazione, che applica effettivamente il filtro all'immagine:

_currentTarget.filters = _currentFilters;

Alla fine, poiché l'ultimo filtro aggiunto non deve essere applicato in via definitiva all'oggetto di visualizzazione in quanto ancora “attivo”, viene rimosso dall'array _currentFilters :

_currentFilters.pop();

La rimozione di questo filtro dall'array non influisce sull'oggetto di visualizzazione filtrato, perché gli oggetti di visualizzazione creano una copia dell'array dei filtri quando vengono assegnati alla proprietà filters e usano questo array interno invece dell'originale. Per questo motivo tutte le modifiche apportate all'array dei filtri non influiscono sull'oggetto di visualizzazione fino a quando l'array non viene assegnato nuovamente alla proprietà filters dell'oggetto di visualizzazione.