Creazione e applicazione di filtri

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

I filtri consentono di applicare alle bitmap e agli oggetti di visualizzazione una vasta gamma di effetti, ad esempio, ombre esterne, smussature e sfocature. Ogni filtro viene definito come classe, pertanto l'applicazione di filtri consiste nella creazione di istanze di oggetti filtro, un'operazione che non è diversa dalla creazione di qualunque altro oggetto. Una volta creata un'istanza di un oggetto filtro, può essere facilmente applicata a un oggetto di visualizzazione mediante la proprietà filters dell'oggetto o, nel caso di un oggetto BitmapData, mediante il metodo applyFilter() .

Creazione di un filtro

Per creare un oggetto filtro, chiamate semplicemente il metodo di costruzione della classe di filtri scelta. Per creare, ad esempio, un oggetto DropShadowFilter, utilizzate il codice seguente:

import flash.filters.DropShadowFilter; 
var myFilter:DropShadowFilter = new DropShadowFilter();

Anche se non viene mostrato in questo esempio, la funzione di costruzione DropShadowFilter() (come tutte le funzioni di costruzione delle classi di filtri) accetta diversi parametri opzionali che possono essere utilizzati per personalizzare l'aspetto dell'effetto filtro.

Applicazione di un filtro

Una volta creato un oggetto filtro, potete applicarlo a un oggetto di visualizzazione o a un oggetto BitmapData; il modo in cui lo applicate dipende dall'oggetto di destinazione.

Applicazione di un filtro a un oggetto di visualizzazione

Quando applicate un filtro a un oggetto di visualizzazione, utilizzate la proprietà filters. La proprietà filters di un oggetto di visualizzazione è un'istanza Array, i cui elementi sono gli oggetti di filtro applicati all'oggetto di visualizzazione. Per applicare un solo filtro a un oggetto di visualizzazione, create l'istanza del filtro, aggiungetela a un'istanza Array e assegnate tale oggetto Array alla proprietà filters dell'oggetto di visualizzazione:

import flash.display.Bitmap; 
import flash.display.BitmapData; 
import flash.filters.DropShadowFilter; 
 
// Create a bitmapData object and render it to screen 
var myBitmapData:BitmapData = new BitmapData(100,100,false,0xFFFF3300); 
var myDisplayObject:Bitmap = new Bitmap(myBitmapData); 
addChild(myDisplayObject); 
 
// Create a DropShadowFilter instance. 
var dropShadow:DropShadowFilter = new DropShadowFilter(); 
 
// Create the filters array, adding the filter to the array by passing it as  
// a parameter to the Array() constructor. 
var filtersArray:Array = new Array(dropShadow); 
 
// Assign the filters array to the display object to apply the filter. 
myDisplayObject.filters = filtersArray;

Se desiderate assegnare più filtri all'oggetto, è sufficiente aggiungere tutti i filtri all'istanza Array prima di assegnarla alla proprietà filters . Potete aggiungere più oggetti a un array assegnandoli come parametri alla relativa funzione di costruzione. Questo codice, ad esempio, applica un filtro smussatura e un filtro bagliore all'oggetto di visualizzazione creato in precedenza:

import flash.filters.BevelFilter; 
import flash.filters.GlowFilter; 
 
// Create the filters and add them to an array. 
var bevel:BevelFilter = new BevelFilter(); 
var glow:GlowFilter = new GlowFilter(); 
var filtersArray:Array = new Array(bevel, glow); 
 
// Assign the filters array to the display object to apply the filter. 
myDisplayObject.filters = filtersArray;

Quando create l'array che contiene i filtri, potete crearlo mediante la funzione di costruzione new Array() (come mostrato negli esempi precedenti) oppure potete utilizzare la sintassi letterale di Array, racchiudendo i filtri tra parentesi quadre ( [] ). La riga di codice seguente, ad esempio:

var filters:Array = new Array(dropShadow, blur); 

ha lo stesso effetto della riga di codice seguente:

var filters:Array = [dropShadow, blur];

Se applicate più filtri agli oggetti di visualizzazione, essi vengono applicati in modo cumulativo e in sequenza. Se, ad esempio, un array filters contiene due elementi, un filtro di smussatura aggiunto per primo e un filtro ombra esterna aggiunto per secondo, il filtro ombra esterno viene applicato sia al filtro smussatura che all'oggetto di visualizzazione. Ciò avviene in virtù del fatto che il filtro ombra esterna occupa la seconda posizione nell'array filters. Se desiderate applicare i filtri in un modo non cumulativo, applicate ogni filtro a una nuova copia dell'oggetto di visualizzazione.

Se assegnate solo pochi filtri a un oggetto di visualizzazione, potete creare l'istanza del filtro e assegnarla all'oggetto in una sola istruzione. La riga di codice seguente, ad esempio, applica un filtro sfocatura a un oggetto di visualizzazione denominato myDisplayObject :

myDisplayObject.filters = [new BlurFilter()];

Il codice precedente crea un'istanza Array mediante la sintassi letterale di Array (parentesi quadre), crea un'istanza BlurFilter come elemento dell'Array e assegna tale Array alla proprietà filters dell'oggetto di visualizzazione denominato myDisplayObject .

Rimozione dei filtri da un oggetto di visualizzazione

Rimuovere tutti i filtri da un oggetto di visualizzazione è un'operazione semplice che comporta l'assegnazione di un valore null alla proprietà filters :

myDisplayObject.filters = null;

Se avete applicato più filtri a un oggetto e desiderate rimuovere un solo filtro, dovete eseguire diverse operazioni per modificare l'array della proprietà filters . Per ulteriori informazioni, vedete Problemi potenziali nelle operazioni con i filtri .

Applicazione di un filtro a un oggetto BitmapData

Per applicare un filtro a un oggetto BitmapData è necessario utilizzare il metodo applyFilter() dell'oggetto BitmapData:

var rect:Rectangle = new Rectangle(); 
var origin:Point = new Point(); 
myBitmapData.applyFilter(sourceBitmapData, rect, origin, new BlurFilter());

Il metodo applyFilter() applica un filtro a un oggetto BitmapData di origine, producendo una nuova immagine filtrata. Questo metodo non modifica l'immagine di origine; piuttosto, il risultato dell'applicazione del filtro all'immagine originale viene memorizzato nell'istanza BitmapData su cui viene chiamato il metodo applyFilter() .

Funzionamento dei filtri

Il filtraggio degli oggetti di visualizzazione funziona mediante la memorizzazione nella cache di una copia dell'oggetto originale sotto forma di bitmap trasparente.

Una volta applicato un filtro a un oggetto di visualizzazione, il runtime memorizza l'oggetto nella cache sotto forma di bitmap fintanto che per l'oggetto è presente un elenco di filtri valido. Questa bitmap di origine viene quindi utilizzata come immagine di origine per tutti gli effetti filtro applicati in seguito.

Ogni oggetto di visualizzazione include in genere due bitmap: una con l'oggetto di visualizzazione di origine non filtrato originale e l'altra per l'immagine finale dopo l'applicazione del filtro. L'immagine finale viene utilizzata al momento del rendering. Se l'oggetto di visualizzazione non viene modificato, l'immagine finale non richiede alcun aggiornamento.

Problemi potenziali nelle operazioni con i filtri

Quando si utilizzano i filtri, è opportuno tenere in considerazione una serie di potenziali fonti di confusione o problemi.

Memorizzazione nella cache di filtri e bitmap

Per applicare un filtro a un oggetto di visualizzazione, è necessario attivare la memorizzazione nella cache per l'oggetto. Quando applicate un filtro a un oggetto di visualizzazione la cui proprietà cacheAsBitmap è impostata su false , la proprietà cacheAsBitmap dell'oggetto viene automaticamente impostata su true . Se successivamente rimuovete tutti i filtri dall'oggetto di visualizzazione, viene ripristinato l'ultimo valore impostato per la proprietà cacheAsBitmap .

Modifica dei filtri in fase di runtime

Se a un oggetto di visualizzazione sono già applicati dei filtri, non potete modificare il set di filtri aggiungendo ulteriori filtri o rimovendoli dall' array della proprietà filters . Per aggiungere o modificare il set di filtri applicati, è necessario invece apportare le modifiche a un array distinto, quindi assegnare tale array alla proprietà filters dell'oggetto di visualizzazione per i filtri da applicare all'oggetto. Il modo più semplice per effettuare questa operazione è quello di leggere l'array della proprietà filters in una variabile Array e apportare le modifiche desiderate a questo array temporaneo. Assegnate quindi nuovamente questo array alla proprietà filters dell'oggetto di visualizzazione. Nei casi più complessi, potrebbe essere necessario mantenere un array principale di filtri distinto. Apportate le modifiche necessarie all'array di filtri principale e riassegnate l'array principale alla proprietà filters dell'oggetto di visualizzazione dopo ogni modifica.

Aggiunta di un ulteriore filtro

Il codice seguente dimostra la procedura per aggiungere un ulteriore filtro a un oggetto di visualizzazione a cui sono già applicati uno o più filtri. Inizialmente, viene applicato un filtro bagliore all'oggetto di visualizzazione denominato myDisplayObject ; quindi, quando viene fatto clic sull'oggetto di visualizzazione, viene chiamata la funzione addFilters() . In questa funzione, vengono applicati due filtri aggiuntivi a myDisplayObject :

import flash.events.MouseEvent; 
import flash.filters.*; 
 
myDisplayObject.filters = [new GlowFilter()]; 
 
function addFilters(event:MouseEvent):void 
{ 
    // Make a copy of the filters array. 
    var filtersCopy:Array = myDisplayObject.filters; 
 
    // Make desired changes to the filters (in this case, adding filters). 
    filtersCopy.push(new BlurFilter()); 
    filtersCopy.push(new DropShadowFilter()); 
 
    // Apply the changes by reassigning the array to the filters property. 
    myDisplayObject.filters = filtersCopy; 
} 
 
myDisplayObject.addEventListener(MouseEvent.CLICK, addFilters);

Rimozione di un filtro da un set di filtri

Se a un oggetto di visualizzazione sono applicati più filtri e desiderate rimuoverne uno lasciando che gli altri filtri continuino a essere applicati all'oggetto, copiate i filtri in un array temporaneo, rimovete il filtro indesiderato dall'array, quindi riassegnate l'array temporaneo alla proprietà filters dell'oggetto di visualizzazione. Nella sezione Recupero di valori e rimozione degli elementi di un array vengono descritti diversi metodi per rimuovere uno o più elementi da un array.

Il metodo più semplice consiste nel rimuovere il filtro di primo livello dell'oggetto (ovvero l'ultimo filtro applicato all'oggetto). Per rimuovere il filtro dall'array, utilizzate il metodo pop() della classe Array:

// Example of removing the top-most filter from a display object  
// named "filteredObject". 
 
var tempFilters:Array = filteredObject.filters; 
 
// Remove the last element from the Array (the top-most filter). 
tempFilters.pop(); 
 
// Apply the new set of filters to the display object. 
filteredObject.filters = tempFilters;

In modo analogo, per rimuovere il filtro che si trova al livello più basso (il primo applicato all'oggetto), utilizzate lo stesso codice, sostituendo il metodo shift() della classe Array al metodo pop() .

Per rimuovere un filtro dalla parte centrale di un array di filtri (presupponendo che l'array contenga più di due filtri), potete usare il metodo splice() . A questo scopo, occorre conoscere la posizione di indice (la posizione nell'array) del filtro da rimuovere. Il codice seguente, ad esempio, rimuove il secondo filtro (nella posizione di indice 1) applicato a un oggetto di visualizzazione:

// Example of removing a filter from the middle of a stack of filters 
// applied to a display object named "filteredObject". 
 
var tempFilters:Array = filteredObject.filters; 
 
// Remove the second filter from the array. It's the item at index 1  
// because Array indexes start from 0. 
// The first "1" indicates the index of the filter to remove; the  
// second "1" indicates how many elements to remove. 
tempFilters.splice(1, 1); 
 
// Apply the new set of filters to the display object. 
filteredObject.filters = tempFilters;

Determinazione della posizione di indice di un filtro

Per conoscere la posizione di indice del filtro, è necessario individuare il filtro da rimuovere dall'array. Dovete conoscere (in virtù del modo in cui è progettata l'applicazione) oppure calcolare la posizione di indice del filtro da rimuovere.

L'approccio migliore consiste nel progettare l'applicazione in modo che il filtro che si desidera rimuovere sia sempre nella stessa posizione nel set di filtri. Se, ad esempio, disponete di un singolo oggetto di visualizzazione a cui sono applicati un filtro di convoluzione e un filtro ombra esterna (in questo ordine) e desiderate rimuovere il filtro ombra esterna mantenendo quello di convoluzione, il filtro deve trovarsi in una posizione nota (quello di primo livello), in modo da sapere in anticipo quale metodo Array utilizzare (in questo caso Array.pop() per rimuovere il filtro ombra esterna).

Se il filtro che desiderate rimuovere è sempre di un certo tipo, ma non necessariamente sempre nella stessa posizione nel set di filtri, potete controllare il tipo di dati di ciascun filtro nell'array per determinare quale rimuovere. Il codice seguente, ad esempio, determina qual è il filtro bagliore in un set di filtri e lo rimuove dal set.

// Example of removing a glow filter from a set of filters, where the 
//filter you want to remove is the only GlowFilter instance applied  
// to the filtered object. 
 
var tempFilters:Array = filteredObject.filters; 
 
// Loop through the filters to find the index of the GlowFilter instance. 
var glowIndex:int; 
var numFilters:int = tempFilters.length; 
for (var i:int = 0; i < numFilters; i++) 
{ 
    if (tempFilters[i] is GlowFilter) 
    { 
        glowIndex = i; 
        break; 
    } 
} 
 
// Remove the glow filter from the array. 
tempFilters.splice(glowIndex, 1); 
 
// Apply the new set of filters to the display object. 
filteredObject.filters = tempFilters;

In casi più complessi, ad esempio quando il filtro da rimuovere viene selezionato in fase di runtime, l'approccio migliore consiste nel mantenere separata una copia persistente dell'array di filtri, da utilizzare come elenco di filtri principale. Ogni volta che modificate il set di filtri, viene modificato l'elenco principale, quindi applicato quell'array di filtri come proprietà filters dell'oggetto di visualizzazione.

Nell'esempio di codice seguente vengono applicati, ad esempio, vari filtri di convoluzione a un oggetto di visualizzazione per creare diversi effetti visivi; quindi, in un punto successivo dell'applicazione, uno di questi filtri viene rimosso mentre gli altri vengono mantenuti. In questo caso, il codice mantiene una copia principale dell'array di filtri, oltre a un riferimento al filtro da rimuovere. L'individuazione e la rimozione del filtro specifico è simile all'approccio precedente, a eccezione del fatto che, anziché creare una copia temporanea dell'array di filtri, viene modificata la copia principale e quindi applicata all'oggetto di visualizzazione.

// Example of removing a filter from a set of  
// filters, where there may be more than one  
// of that type of filter applied to the filtered  
// object, and you only want to remove one. 
 
// A master list of filters is stored in a separate, 
// persistent Array variable. 
var masterFilterList:Array; 
 
// At some point, you store a reference to the filter you 
// want to remove. 
var filterToRemove:ConvolutionFilter; 
 
// ... assume the filters have been added to masterFilterList, 
// which is then assigned as the filteredObject.filters: 
filteredObject.filters = masterFilterList; 
 
// ... later, when it's time to remove the filter, this code gets called: 
 
// Loop through the filters to find the index of masterFilterList. 
var removeIndex:int = -1; 
var numFilters:int = masterFilterList.length; 
for (var i:int = 0; i < numFilters; i++) 
{ 
    if (masterFilterList[i] == filterToRemove) 
    { 
        removeIndex = i; 
        break; 
    } 
} 
 
if (removeIndex >= 0) 
{ 
    // Remove the filter from the array. 
    masterFilterList.splice(removeIndex, 1); 
 
    // Apply the new set of filters to the display object. 
    filteredObject.filters = masterFilterList; 
}

In questo caso (nel confrontare il riferimento a un filtro memorizzato con gli elementi nell'array di filtri per determinare quale filtro rimuovere), è necessario mantenere una copia separata dell'array di filtri; il codice, infatti, non funziona se si confronta il riferimento a un filtro memorizzato con gli elementi di un array temporaneo copiato dalla proprietà filters dell'oggetto di visualizzazione. Ciò è dovuto al fatto che internamente, quando assegnate un array alla proprietà filters , il runtime crea una copia di ogni oggetto filtro presente nell'array. All'oggetto di visualizzazione vengono applicate queste copie (anziché gli oggetti originali); quando leggete la proprietà filters in un array temporaneo, questo contiene i riferimenti agli oggetti filtro copiati anziché i riferimenti agli oggetti filtro originali. Di conseguenza, se nell'esempio precedente tentate di determinare la posizione di indice di filterToRemove confrontandolo con i filtri in un array di filtri temporaneo, non verrà trovata alcuna corrispondenza.

Filtri e trasformazioni degli oggetti

Nella superficie relativa agli obiettivi del rilevamento per zone (operazione che consente di determinare se un'istanza si sovrappone o si interseca con un'altra) non sono presenti regioni filtrate (ad esempio, ombra esterna) al di fuori del rettangolo del riquadro di delimitazione dell'oggetto di visualizzazione. Poiché i metodi di rilevamento per zone della classe DisplayObject si basano sui vettori, non è possibile eseguirli sulla bitmap risultante. Ad esempio, se si applica un filtro smussatura all'istanza di un pulsante, non è possibile eseguire il rilevamento per zone sulla parte smussata dell'istanza.

La modifica in scala, la rotazione e l'inclinazione non sono supportate da filtri. Se l'oggetto di visualizzazione filtrato viene modificato in scala ( scaleX e scaleY non sono al 100%), l'effetto di filtro non viene modificato in scala con l'istanza. In altre parole, la forma originale dell'istanza viene ruotata, modificata in scala o inclinata; tuttavia, il filtro non viene ruotato, modificato in scala o inclinato con l'istanza.

È possibile animare un'istanza con un filtro per creare effetti realistici o nidificare istanze e utilizzare la classe BitmapData per animare i filtri in modo da ottenere l'effetto specificato.

Filtri e oggetti Bitmap

Quando applicate un filtro a un oggetto BitmapData, la proprietà cacheAsBitmap viene automaticamente impostata su true . In tal modo, il filtro viene di fatto applicato alla copia dell'oggetto anziché all'originale.

Questa copia viene quindi posizionata nella vista principale (sopra l'oggetto originale) più vicino possibile al pixel più vicino. Se i limiti della bitmap originale cambiano, la copia filtrata viene ricreata dall'originale anziché essere allungata o distorta.

Se rimovete tutti i filtri di un oggetto di visualizzazione, la proprietà cacheAsBitmap viene reimpostata sul valore precedente all'applicazione del filtro.