Filters maken en toepassen

Flash Player 9 of hoger, Adobe AIR 1.0 of hoger

Met filters kunt u een reeks effecten toepassen op bitmap- en weergaveobjecten die variëren van slagschaduwen tot schuine kanten en vervagingen. Elk filter wordt gedefinieerd als een klasse. Bij het toepassen van filters worden dan ook instanties van filterobjecten gemaakt, net als bij het maken van elk ander object. Wanneer u een instantie van een filterobject hebt gemaakt, kan deze eenvoudig worden toegepast op een weergaveobject met de eigenschap filters van het object of, in het geval van een object BitmapData, met de methode applyFilter() .

Een filter maken

Om een filterobject te maken, roept u gewoon de constructormethode van de door u geselecteerde filterklasse aan. Om bijvoorbeeld een DropShadowFilter-object te maken, gebruikt u de volgende code:

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

Hoewel ze hier niet worden getoond, accepteert de constructor DropShadowFilter() (net als alle constructors van filterklassen) diverse optionele parameters die kunnen worden gebruikt om de weergave van het filtereffect aan te passen.

Een filter toepassen

Wanneer u een filterobject hebt gemaakt, kunt u deze toepassen op een weergaveobject of een object BitmapData. De wijze waarop u het filter toepast, hangt af van het object waarop het filter wordt toegepast.

Een filter toepassen op een weergaveobject

Wanneer u filtereffecten toepast op een weergaveobject, doet u dit via de eigenschap filters . De eigenschap filters van een weergaveobject is een instantie Array waarvan de elementen de filterobjecten zijn die worden toegepast op het weergaveobject. Wanneer u een enkel filter op een weergaveobject wilt toepassen, maakt u de filterinstantie, voegt u deze toe aan een instantie Array en wijst u dat object Array aan de eigenschap filters van het weergaveobject toe:

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;

Als u meerdere filters wilt toewijzen aan het object, kunt u alle filters toevoegen aan de instantie Array voordat u deze toewijst aan de eigenschap filters . U kunt meerdere objecten toevoegen aan een array door deze als parameters door te geven aan de constructor. Deze code past bijvoorbeeld een schuine-kantfilter en een gloedfilter toe op het eerder gemaakte weergaveobject.

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;

Wanneer u de array met de filters maakt, kunt u deze maken met behulp van de constructor new Array() (zoals wordt getoond in de voorgaande voorbeelden) of u kunt gebruikmaken van de literale Array-syntaxis door de filters tussen vierkante haakjes ( [] ) te zetten. Deze coderegel bijvoorbeeld:

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

doet hetzelfde als deze coderegel:

var filters:Array = [dropShadow, blur];

Wanneer u meerdere filters toepast op weergaveobjecten, worden deze op een cumulatieve, opeenvolgende wijze toegepast. Wanneer een array filters bijvoorbeeld twee elementen bevat, waarbij een schuine-kantfilter als eerste en een slagschaduwfilter als tweede is toegevoegd, wordt het slagschaduwfilter toegepast op zowel het schuine-kantfilter als het weergaveobject. Dit komt doordat het slagschaduwfilter de tweede positie in de array filters inneemt. Als u filter op een niet-cumulatieve manier wilt toepassen, past u elke filter toe op een nieuwe kopie van het weergaveobject.

Wanneer u slechts één filter of een paar filters toewijst aan een weergaveobject, kunt u een filterinstantie maken en deze in een enkele instructie toewijzen aan het object. De volgende coderegel past bijvoorbeeld een vervagend filter toe op een weergaveobject myDisplayObject .

myDisplayObject.filters = [new BlurFilter()];

De vorige code maakt een Array-instantie met een letterlijke Array-syntaxis (vierkante haakjes), een BlurFilter-instantie als een element in Array en wijst die Array toe aan de eigenschap filters van het weergaveobject myDisplayObject .

Filters verwijderen uit een weergaveobject

Het verwijderen van alle filters uit een weergaveobject is net zo eenvoudig als het toewijzen van een waarde null aan de eigenschap filters :

myDisplayObject.filters = null;

Wanneer u meerdere filters hebt toegepast op een object en u wilt slechts een van de filters verwijderen, moet u diverse stappen doorlopen om de array met eigenschap filters te wijzigen. Zie Potentiële problemen bij het werken met filters voor meer informatie.

Een filter toepassen op een object BitmapData

Wanneer u een filter wilt toepassen op een object BitmapData, moet u gebruikmaken van de methode applyFilter() van het object BitmapData:

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

De methode applyFilter() past een filter toe op een bronobject BitmapData en produceert een nieuwe, gefilterde afbeelding. Deze methode wijzigt niet de oorspronkelijke bronafbeelding. In plaats daarvan wordt het resultaat van het filter dat wordt toegepast op de bronafbeelding, opgeslagen in de instantie BitmapData waarvoor de methode applyFilter() wordt aangeroepen.

De werking van filters

Bij het filteren van weergaveobjecten wordt een kopie van het oorspronkelijke object als een transparante bitmap in cache geplaatst.

Wanneer een filter op een weergaveobject is toegepast, slaat de runtime het object op als een bitmap, zolang het object een geldige filterlijst heeft. Deze bronbitmap wordt vervolgens gebruikt als de oorspronkelijke afbeelding voor alle volgende toegepaste filtereffecten.

Weergaveobjecten bevatten meestal twee bitmaps: een bitmap met het oorspronkelijk ongefilterde bronweergaveobject en een bitmap voor de uiteindelijke afbeelding na filtering. De uiteindelijke afbeelding wordt voor weergave gebruikt. Zolang het weergaveobject niet wordt gewijzigd, hoeft de uiteindelijke afbeelding niet te worden bijgewerkt.

Potentiële problemen bij het werken met filters

Er zijn diverse potentiële oorzaken die kunnen leiden tot verwarring of problemen wanneer u werkt met filters.

Filters en bitmap in cache plaatsen

Wanneer u een filter wilt toepassen op een weergaveobject, moet het in cache plaatsen van een bitmap zijn ingeschakeld voor dat object. Wanneer u een filter op een weergaveobject toepast, waarvan de eigenschap cacheAsBitmap is ingesteld op false , wordt de eigenschap cacheAsBitmap van het object automatisch ingesteld op true . Als u later alle filters van het weergaveobject verwijdert, wordt de eigenschap cacheAsBitmap teruggezet naar de vorige waarde.

Filters wijzigen bij uitvoering

Als er op een weergaveobject al een of meer filters zijn toegepast, kunt u de set filters niet wijzigen door extra filters toe te voegen of door filters te verwijderen uit de array met eigenschappen filters . In plaats daarvan moet u, om wijzigingen aan te brengen in de set filters die wordt toegepast, de gewenste wijzigingen doorvoeren in een afzonderlijke array, waarna u deze array toewijst aan de array met eigenschappen filter van het weergaveobject voor de filters die op het object worden toegepast. De eenvoudigste manier om dit te doen is door de array met eigenschappen filters in een willekeurige variabele Array in te lezen en uw wijzigingen in deze tijdelijke array aan te brengen. Vervolgens wijst u deze array weer toe aan de eigenschap filters van het weergaveobject. In complexere gevallen kan het zijn dat u een afzonderlijke hoofdarray met filters moet maken. U brengt de wijzigingen aan in de hoofdarray met filters en na elke wijziging wijst u de hoofdarray toe aan de eigenschap filters van het weergaveobject.

Extra filters toevoegen

In de volgende code wordt geïllustreerd hoe u een extra filter toevoegt aan een weergaveobject waarop al een of meer filters zijn toegepast. Eerst wordt een gloedfilter toegepast op het weergaveobject met de naam myDisplayObject . Wanneer later op het weergaveobject wordt geklikt, wordt de functie addFilters() aangeroepen. In deze functie worden twee aanvullende filters toegepast op 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);

Eén filter uit een set filters verwijderen

Als er meerdere filters op een weergaveobject zijn toegepast en u wilt een van deze filters verwijderen (waarbij de andere filters op het object toegepast blijven), gaat u als volgt te werk: kopieer de filters naar een tijdelijke array, verwijder het ongewenste filter uit deze array en wijs de tijdelijke array toe aan de eigenschap filters van het weergaveobject. In Waarden ophalen en arrayelementen verwijderen worden verschillende manieren beschreven waarop u een of meer elementen uit een array kunt verwijderen.

De meest voor de hand liggende situatie is het verwijderen van het bovenste filter van het object (het laatste filter dat op het object is toegepast). Gebruik de methode pop() van de klasse Array om het filter uit de array te verwijderen:

// 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;

Om het onderste filter te verwijderen (het eerste filter dat op het object is toegepast) gebruikt u dezelfde code, waarbij u de methode pop() van de klasse Array vervangt door de methode shift() .

Als u een filter in het midden van een array met filters wilt verwijderen (indien de array meer dan twee filters bevat), kunt u de methode splice() gebruiken. U moet weten wat de index (de positie in de array) is van het filter dat u wilt verwijderen. Met de volgende code verwijdert u bijvoorbeeld het tweede filter (het filter op index 1) van een weergaveobject:

// 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;

De index van een filter bepalen

U moet weten welk filter u uit de array wilt verwijderen, dus u moet weten wat de index van dat filter is. Het kan zijn dat de index van het filter dat u wilt verwijderen bekend is (als gevolg van de manier waarop de toepassing is ontworpen), anders moet u deze berekenen.

Het is het handigste om de toepassing zo te ontwerpen dat het filter dat u wilt verwijderen altijd dezelfde positie inneemt in de set filters. Stel dat u één weergaveobject hebt waarop een convolutiefilter en een slagschaduwfilter zijn toegepast (in die volgorde) en u wilt het slagschaduwfilter verwijderen maar het convolutiefilter behouden. U weet dan op welke positie het filter zich bevindt (het bovenste filter), zodat u meteen weet welke Array-methode u moet gebruiken (in dit geval Array.pop() ) om het slagschaduwfilter te verwijderen.

Als het filter dat u wilt verwijderen altijd een bepaald type is, maar zich niet altijd op dezelfde positie in de set filters bevindt, kunt u het gegevenstype van elk filter in de array vaststellen om te bepalen welk filter u moet verwijderen. Met de volgende code kunt u bijvoorbeeld bepalen welk filter in een set filter een gloedfilter is en dit filter vervolgens uit de set verwijderen.

// 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 complexere gevallen, bijvoorbeeld als het filter dat verwijderd moet worden tijdens runtime moet worden geselecteerd, kunt u het beste een afzonderlijk en onveranderlijk exemplaar van de filterarray opslaan als de hoofdlijst met filters. Wanneer u een wijziging aanbrengt in de set filters, wijzigt u de hoofdlijst en past u vervolgens de filterarray toe als de eigenschap filters van het weergaveobject.

In de volgende code worden bijvoorbeeld meerdere convolutiefilters toegepast op een weergaveobject om verschillende visuele effecten aan te brengen. Later wordt een van deze filters verwijderd, terwijl de andere behouden blijven. In dit geval wordt een hoofdarray met filters en een verwijzing naar het filter dat verwijderd moet worden opgeslagen. Het zoeken naar en het verwijderen van het specifieke filter verloopt hetzelfde als de hiervoor beschreven procedure, alleen wordt er geen tijdelijk exemplaar van de array met filters gemaakt, maar de hoofdarray wordt bewerkt en vervolgens op het weergaveobject toegepast.

// 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 deze procedure (wanneer u een opgeslagen filterverwijzing vergelijkt met de items in de array met filters om te bepalen welk filter verwijderd moet worden) moet u een afzonderlijk exemplaar van de array met filters opslaan. De code werkt niet als u de opgeslagen filterverwijzing vergelijkt met de elementen in de tijdelijke array die is gekopieerd van de eigenschap filters van het weergaveobject. Dit gebeurt, omdat de runtime intern een kopie maakt van elk filterobject in de array, wanneer u een array aan de eigenschap filters toewijst. Deze kopieën (en dus niet de oorspronkelijke objecten) worden op het weergaveobject toegepast. Wanneer u vervolgens de eigenschap filters in de tijdelijke array inleest, bevat de tijdelijke array verwijzingen naar de gekopieerde filterobjecten in plaats van verwijzingen naar de oorspronkelijke filterobjecten. Als u vervolgens in het voorgaande voorbeeld probeert te bepalen wat de index van filterToRemove is door dit te vergelijken met de filters in een tijdelijke array met filters, wordt er geen overeenkomst gevonden.

Filters en objecttransformaties

Geen enkel gefilterd gebied (bijvoorbeeld slagschaduw) buiten het begrenzende vak van een weergaveobject wordt beschouwd als een onderdeel van het oppervlak voor raakdetectiedoeleinden (bepalen of een instantie een andere instantie overlapt of doorsnijdt). Omdat raakdetectie is gebaseerd op vectoren, kunt u geen raakdetectie uitvoeren op het bitmapresultaat. Wanneer u bijvoorbeeld een schuine-kantfilter toepast op een knopinstantie, is de raakdetectie niet beschikbaar op het schuine-kantdeel van de instantie.

Schalen, roteren en scheeftrekken worden niet ondersteund door filters. Wanneer het gefilterde weergaveobject zelf is geschaald (wanneer scaleX en scaleY niet 100% zijn), schaalt het filtereffect niet met de instantie mee. Dit betekent dat de oorspronkelijke vorm van de instantie roteert, schaalt of scheeftrekt, maar het filter roteert of schaalt niet en trekt niet scheef met de instantie.

U kunt een instantie laten bewegen met een filter om realistische effecten te maken of instanties nesten en de klasse BitmapData gebruiken om filters te laten bewegen om dit effect te bereiken.

Filters en objecten Bitmap

Wanneer u een filter toepast op een object BitmapData, wordt de eigenschap cacheAsBitmap automatisch ingesteld op true . Op deze manier wordt het filter feitelijk toegepast op de kopie van het object in plaats van op het origineel.

Deze kopie wordt vervolgens zo dicht mogelijk bij de dichtstbijzijnde pixel op de hoofdweergave (over het oorspronkelijke object) geplaatst. Wanneer de grenzen van de bitmap worden gewijzigd, wordt de gefilterde kopie van de bitmap opnieuw op basis van het origineel gemaakt en dus niet uitgerekt of vervormd.

Wanneer u alle filters voor een weergaveobject wist, wordt de eigenschap cacheAsBitmap opnieuw ingesteld op de waarde waarop deze was ingesteld voor de toepassing van het filter.