Bitmapvoorbeeld: geanimeerde draaiende maan

Flash Player 9 of hoger, Adobe AIR 1.0 of hoger

Het voorbeeld van een geanimeerde draaiende maan demonstreert technieken voor het werken met objecten Bitmap en afbeeldingsgegevens van een bitmap (objecten BitmapData). In het voorbeeld wordt een animatie gemaakt van een draaiende, bolvormige maan, waarbij gebruik wordt gemaakt van een platte afbeelding van het oppervlak van de maan als onbewerkte afbeeldingsgegevens. De volgende technieken worden getoond:

  • Het laden van een externe afbeelding en het werken met de onbewerkte afbeeldingsgegevens ervan

  • Het maken van animatie door herhaaldelijk pixels te kopiëren van andere delen van een bronafbeelding

  • Bitmapafbeelding maken door pixelwaarden in te stellen

Zie www.adobe.com/go/learn_programmingAS3samples_flash_nl als u de toepassingsbestanden voor dit voorbeeld wilt downloaden. U vindt de toepassingsbestanden voor de geanimeerde draaiende maan in de map Samples/SpinningMoon. De toepassing bestaat uit de volgende bestanden:

Bestand

Beschrijving

SpinningMoon.mxml

of

SpinningMoon.fla

Het hoofdtoepassingsbestand in Flex (MXML) of Flash (FLA).

com/example/programmingas3/moon/MoonSphere.as

Klasse die de functionaliteit uitvoert van het laden, weergeven en bewegen van de maan.

moonMap.png

Afbeeldingsbestand met een foto van het oppervlak van de maan, die wordt geladen en gebruikt om de geanimeerde draaiende maan te maken.

Externe afbeelding als bitmapgegevens laden

De eerste hoofdtaak die u uitvoert, is het laden van een extern afbeeldingsbestand: een foto van het oppervlak van de maan. De laadbewerking wordt afgehandeld door twee methoden in de klasse MoonSphere: de constructor MoonSphere(), waar het laadproces wordt gestart, en de methode imageLoadComplete(), die wordt aangeroepen als de externe afbeelding volledig is geladen.

Het laden van een externe afbeelding komt overeen met het laden van een extern SWF-bestand. Beide gebruiken een instantie van de klasse flash.display.Loader voor het uitvoeren van de laadbewerking. De werkelijke code van de methode MoonSphere() waarmee het laden van de afbeelding wordt gestart, is als volgt:

var imageLoader:Loader = new Loader(); 
imageLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadComplete); 
imageLoader.load(new URLRequest("moonMap.png"));

De eerste regel declareert de instantie Loader met de naam imageLoader. De derde regel begint daadwerkelijk het laadproces door de methode load() van het object Loader aan te roepen, waarbij een instantie URLRequest wordt doorgegeven die de URL vertegenwoordigt van de afbeelding die moet worden geladen. De tweede regel stelt de gebeurtenislistener in die wordt geactiveerd wanneer de afbeelding volledig is geladen. De methode addEventListener() wordt niet aangeroepen voor de instantie Loader zelf, maar aangeroepen voor de eigenschap contentLoaderInfo van het object Loader. De instantie Loader verzendt zelf geen gebeurtenissen met betrekking tot de inhoud die wordt geladen. De eigenschap contentLoaderInfo ervan bevat echter een verwijzing naar het object LoaderInfo dat is gekoppeld aan de inhoud die wordt geladen in het object Loader (in dit geval de externe afbeelding). Dat object LoaderInfo biedt wel verschillende gebeurtenissen met betrekking tot de voortgang en voltooiing van het laden van de externe inhoud, waaronder de gebeurtenis complete (Event.COMPLETE) die een aanroep van de methode imageLoadComplete() activeert wanneer de afbeelding volledig is geladen.

Hoewel het starten van het laden van de externe afbeelding een belangrijk onderdeel van het proces vormt, is het net zo belangrijk om te weten wat moet worden gedaan nadat het laden is voltooid. Zoals getoond in de code hierboven, wordt de functie imageLoadComplete() aangeroepen wanneer de afbeelding is geladen. Die functie doet verschillende dingen met geladen afbeeldingsgegevens, die hieronder worden beschreven. De afbeeldingsgegevens kunnen echter alleen worden gebruikt wanneer ze kunnen worden benaderd. Wanneer een object Loader wordt gebruikt om een externe afbeelding te laden, wordt de geladen afbeelding een instantie Bitmap die is gekoppeld als een onderliggend weergaveobject van het object Loader. In dit geval is de instantie Loader beschikbaar voor de gebeurtenislistenermethode als onderdeel van het gebeurtenisobject dat als parameter aan de methode wordt doorgegeven. De eerste regels van de methode imageLoadComplete() zijn als volgt:

private function imageLoadComplete(event:Event):void 
{ 
    textureMap = event.target.content.bitmapData; 
    ... 
}

De gebeurtenisobjectparameter heeft de naam event en is een instantie van de klasse Event. Elke instantie van de klasse Event heeft een eigenschap target die verwijst naar het object dat de gebeurtenis activeert (in dit geval de instantie LoaderInfo waarvoor de methode addEventListener() is aangeroepen, zoals hierboven beschreven). Het object LoaderInfo heeft op zijn beurt een eigenschap content die (zodra het laadproces is voltooid) de instantie Bitmap bevat met de geladen bitmapafbeelding. Wanneer u de afbeelding direct op het scherm wilt weergegeven, kunt u deze instantie Bitmap (event.target.content) koppelen aan een weergaveobjectcontainer. (U kunt het object Loader ook aan een weergaveobjectcontainer koppelen.) In dit voorbeeld wordt de geladen inhoud echter gebruikt als bron van onbewerkte afbeeldingsgegevens in plaats van dat deze op het scherm wordt weergegeven. De eerste regel van de imageLoadComplete()-methode leest de bitmapData-eigenschap van de geladen Bitmap-instantie (event.target.content.bitmapData) en slaat deze op in de instantievariabele textureMap, die als bron van de afbeeldingsgegevens wordt gebruikt om de animatie van de roterende maan te maken. Dit wordt hieronder beschreven.

Animatie maken door pixels te kopiëren

Een basisdefinitie van een animatie is de illusie van beweging, of verandering, die wordt veroorzaakt door een afbeelding gedurende een tijdsperiode te veranderen. In dit voorbeeld is het doel het maken van het beeld van een bolvormige maan die rond zijn verticale as draait. Voor deze animatie kunt u het bolvormige vervormingsaspect echter negeren. Bekijk de werkelijke afbeelding die wordt geladen en gebruikt als de bron van de maanafbeeldingsgegevens:

Zoals u kunt zien, bestaat deze afbeelding niet uit een of meer bollen, maar is deze een rechthoekige foto van het oppervlak van de maan. Omdat de foto precies bij de evenaar van de maan is genomen, zijn de delen van de afbeelding die zich dichter bij de boven- en onderkant bevinden, uitgerekt en vervormd. Voor het verwijderen van deze vervorming uit de afbeelding en het bolvormiger maken van de afbeelding, gebruikt u een verschuivingskaartfilter, zoals later wordt beschreven. Omdat deze bronafbeelding rechthoekig is, moet de code de foto van het maanoppervlak gewoon horizontaal bewegen om de illusie te creëren, dat de bol draait.

De afbeelding bevat eigenlijk twee exemplaren van de foto van het maanoppervlak naast elkaar. Deze afbeelding is de bronafbeelding waaruit afbeeldingsgegevens herhaaldelijk worden gekopieerd om de illusie van beweging te maken. Wanneer twee exemplaren van de afbeelding naast elkaar liggen, is het eenvoudiger een doorlopend, ononderbroken schuifeffect te maken. Het animatieproces wordt hieronder stap voor stap beschreven.

Het proces bestaat eigenlijk uit twee afzonderlijke ActionScript-objecten. Het eerste object is de geladen bronafbeelding, die in de code wordt vertegenwoordigd door de instantie BitmapData met de naam textureMap. Zoals eerder beschreven, wordt textureMap gevuld met afbeeldingsgegevens zodra de externe afbeelding is geladen. Hiervoor wordt de volgende code gebruikt:

textureMap = event.target.content.bitmapData;

De inhoud van textureMap is de rechthoekige afbeelding van de maan. Om een geanimeerde rotatie te maken, gebruikt de code een Bitmapinstantiesphere, dit is het werkelijke weergaveobject dat de maan op het scherm weergeeft. Op dezelfde manier als bij textureMap wordt het object sphere gemaakt en gevuld met de oorspronkelijke afbeeldingsgegevens uit de methode imageLoadComplete(), waarbij de volgende code wordt gebruikt:

sphere = new Bitmap(); 
sphere.bitmapData = new BitmapData(textureMap.width / 2, textureMap.height); 
sphere.bitmapData.copyPixels(textureMap, 
                         new Rectangle(0, 0, sphere.width, sphere.height), 
                         new Point(0, 0));

Zoals de code laat zien, wordt sphere geïnstantieerd. De eigenschap bitmapData (de onbewerkte afbeeldingsgegevens die door sphere worden weergegeven) wordt gemaakt met dezelfde hoogte en half de breedte van textureMap. Met andere woorden, de inhoud van sphere krijgt de grootte van één maanfoto (aangezien de afbeelding textureMap twee maanfoto’s naast elkaar bevat). Vervolgens wordt de eigenschap bitmapData gevuld met afbeeldingsgegevens via de methode copyPixels(). De parameters in de aanroep van de methode copyPixels() geven verschillende handelingen aan:

  • De eerste parameter geeft aan dat de afbeeldingsgegevens worden gekopieerd van textureMap.

  • De tweede parameter, een nieuwe instantie Rectangle, geeft aan van welk deel van de textureMap de momentopname moet worden genomen. In dit geval is de momentopname een rechthoek die begint in de linkerbovenhoek van textureMap (zoals aangegeven door de eerste twee parameters Rectangle(): 0, 0) en komen de breedte en de hoogte van de momentopname overeen met de eigenschappen width en height van sphere.

  • De derde parameter, een nieuwe instantie Point met de x- en y-waarden 0, definieert de bestemming van de pixelgegevens, in dit geval de linkerbovenhoek (0, 0) van sphere.bitmapData.

Zoals zichtbaar weergegeven in de afbeelding hieronder, kopieert de code de pixels van textureMap en plakt deze op sphere. Met andere woorden, de BitmapData-inhoud van sphere is het hieronder gemarkeerde deel van textureMap:

Dit is echter alleen nog maar de eerste status van sphere (de eerste afbeeldingsinhoud die op sphere wordt gekopieerd).

Nu de bronafbeelding is geladen en sphere is gemaakt, bestaat de laatste taak van de methode imageLoadComplete() uit het instellen van de animatie. De animatie werkt op basis van een instantie Timer met de naam rotationTimer, die wordt gemaakt en geactiveerd met de volgende code:

var rotationTimer:Timer = new Timer(15); 
rotationTimer.addEventListener(TimerEvent.TIMER, rotateMoon); 
rotationTimer.start();

De code maakt eerst een instantie Timer met de naam rotationTimer. De parameter die is doorgegeven aan de constructor Timer() geeft aan dat rotationTimer de gebeurtenis timer elke 15 milliseconden moet activeren. Vervolgens wordt de methode addEventListener() aangeroepen en wordt opgegeven dat wanneer de gebeurtenis timer optreedt (TimerEvent.TIMER), de methode rotateMoon() wordt aangeroepen. Ten slotte wordt de timer daadwerkelijk gestart door de methode start() ervan aan te roepen.

Door de manier waarop rotationTimer is gedefinieerd, roept Flash Player de methode rotateMoon() in de klasse MoonSphere ongeveer elke 15 milliseconden aan, waardoor beweging van de maan plaatsvindt. De broncode van de rotateMoon()-methode is als volgt:

private function rotateMoon(event:TimerEvent):void 
{ 
    sourceX += 1; 
    if (sourceX > textureMap.width / 2) 
    { 
        sourceX = 0; 
    } 
     
    sphere.Data.copyPixels(textureMap, 
                                    new Rectangle(sourceX, 0, sphere.width, sphere.height), 
                                    new Point(0, 0)); 
     
    event.updateAfterEvent(); 
}

In deze code gebeuren drie dingen:

  1. De waarde van de variabele sourceX (oorspronkelijk op 0 ingesteld) neemt met 1 toe.

    sourceX += 1;

    Zoals u zult zien, wordt sourceX gebruikt om de locatie te bepalen in textureMap waarvan de pixels worden gekopieerd op sphere, zodat met deze code het effect wordt bereikt dat de rechthoek met één pixel naar rechts op textureMap beweegt. Zoals weergegeven in de afbeelding, is de bronrechthoek na enkele animatiecycli met verschillende pixels naar rechts verplaatst:

    Na verloop van meer animatiecycli is de rechthoek nog verder verplaatst:

    Deze geleidelijke, evenwichtige verschuiving van de locatie waarvan de pixels worden gekopieerd, vormt de sleutel tot animatie. Door de bronlocatie langzaam en continu naar rechts te verplaatsen, lijkt het alsof de afbeelding die op het scherm wordt weergegeven in sphere continu naar links schuift. Dit is de reden waarom de bronafbeelding (textureMap) twee exemplaren nodig heeft van de foto van het maanoppervlak. Omdat de rechthoek continu naar rechts beweegt, bevindt deze zich het merendeel van de tijd niet boven één enkele maanfoto worden de twee maanfoto’s overlapt.

  2. Er kleeft één probleem aan de langzaam naar rechts bewegende bronrechthoek. Na verloop van tijd bereikt de rechthoek de rechterrand van textureMap en zijn er geen maanfotopixels meer over om op sphere te kopiëren:

    Met de volgende coderegels wordt dit probleem opgelost:

    if (sourceX >= textureMap.width / 2) 
    { 
        sourceX = 0; 
    }

    De code controleert of sourceX (de linkerrand van de rechthoek) het midden van textureMap heeft bereikt. Zo ja, dan herstelt de code de waarde van sourceX naar 0, waardoor de rechthoek weer naar de linkerrand van textureMap wordt verplaatst en de cyclus opnieuw wordt gestart:

  3. Nu de juiste waarde van sourceX is berekend, bestaat de laatste stap van het maken van de animatie uit het daadwerkelijk kopiëren van de nieuwe bronrechthoekpixels op sphere. De code waarmee dit wordt gedaan, lijkt sterk op de code die sphere eerder vulde (eerder beschreven); het enige verschil is dat in dit geval, in de constructoraanroep new Rectangle(), de linkerrand van de rechthoek op sourceX wordt geplaatst:

    sphere.bitmapData.copyPixels(textureMap, 
                                new Rectangle(sourceX, 0, sphere.width, sphere.height), 
                                new Point(0, 0));

Deze code wordt herhaaldelijk aangeroepen, elke 15 milliseconden. Omdat de locatie van de bronrechthoek continu verschuift en de pixels op sphere worden gekopieerd, lijkt het op het scherm alsof de maanfoto die wordt vertegenwoordigd door sphere voortdurend schuift. Met andere woorden, het lijkt alsof de maan voortdurend draait.

Bolvormig uiterlijk maken

De maan is uiteraard een bol en geen rechthoek. Daarom moet het voorbeeld de voortdurend draaiende rechthoekige foto van het maanoppervlak in een bol omzetten. Dit proces omvat twee afzonderlijke stappen: het gebruik van een masker om alle inhoud te verbergen behalve een cirkelvormig gebied van de foto van het maanoppervlak en het gebruik van een verschuivingskaartfilter om het uiterlijk van de maanfoto te vervormen en het driedimensionaal te laten lijken.

Eerst wordt een cirkelvormig masker gebruikt om alle inhoud van het object MoonSphere te verbergen, met uitzondering van de bol die door het filter is gemaakt. De volgende code maakt het masker als een instantie Shape en past deze toe als het masker van de instantie MoonSphere:

moonMask = new Shape(); 
moonMask.graphics.beginFill(0); 
moonMask.graphics.drawCircle(0, 0, radius); 
this.addChild(moonMask); 
this.mask = moonMask;

Omdat MoonSphere een weergaveobject is (het is gebaseerd op de klasse Sprite), kan het masker direct op de instantie MoonSphere wordt toegepast met gebruik van de overgeërfde eigenschap mask.

Het alleen verbergen van delen van de foto via een cirkelvormig masker is niet genoeg om een realistische draaiende bol te maken. Vanwege de manier waarop de foto van het maanoppervlak is genomen, zijn de afmetingen niet proportioneel; de delen van de afbeelding die zich bij de boven- of onderkant van de afbeelding bevinden, zijn meer vervormd en uitgerekt in vergelijking met de delen van de evenaar. Er wordt een verschuivingskaartfilter gebruikt om de weergave van de maanfoto te vervormen om deze meer driedimensionaal te laten lijken.

Een verschuivingskaartfilter is een type filter dat wordt gebruikt om een afbeelding te vervormen. In dit geval wordt de maanfoto ‘vervormd’ om de foto realistischer te maken. De boven- en onderkant van de afbeelding worden hiertoe horizontaal samengedrukt, terwijl het midden ongewijzigd blijft. Vooropgesteld dat het filter werkt op een vierkant deel van de foto, zorgt het samendrukken van de boven- en onderkant ervoor dat het vierkant wordt veranderd in een cirkel. Een bijeffect van het bewegen van deze vervormde afbeelding is dat het midden van de afbeelding met meer pixels lijkt te worden verplaatst dan de gebieden die zich dicht bij de boven- en onderkant bevinden; dit zorgt voor de illusie dat de cirkel een driedimensionaal object is (een bol).

De volgende code wordt gebruikt om het verschuivingskaartfilter displaceFilter te maken:

var displaceFilter:DisplacementMapFilter; 
displaceFilter = new DisplacementMapFilter(fisheyeLens, 
                                new Point(radius, 0),  
                                BitmapDataChannel.RED, 
                                BitmapDataChannel.GREEN, 
                                radius, 0);

De eerste parameter, fisheyeLens, staat bekend als de kaartafbeelding; in dit geval is het een object BitmapData dat programmatisch wordt gemaakt. De creatie van die afbeelding wordt beschreven in Bitmapafbeelding maken door pixelwaarden in te stellen. De overige parameters beschrijven de positie in de gefilterde afbeelding waarop het filter moet worden toegepast, welke kleurkanalen moeten worden gebruikt om het verschuivingseffect te beheren en in welke mate deze de verschuiving beïnvloeden. Zodra het verschuivingskaartfilter is gemaakt, wordt dit toegepast op sphere, nog steeds binnen de methode imageLoadComplete():

sphere.filters = [displaceFilter];

De uiteindelijke afbeelding, met toegepast masker en verschuivingskaartfilter, ziet er als volgt uit:

Met elke cyclus van de draaiende maananimatie wordt de BitmapData-inhoud van sphere overschreven door een nieuwe momentopname van de bronafbeeldingsgegevens. Het filter hoeft echter niet telkens opnieuw te worden toegepast. Dit komt omdat het filter wordt toegepast op de instantie Bitmap (het weergaveobject) in plaats van op de bitmapgegevens (de onbewerkte pixelinformatie). De instantie Bitmap bevat niet de daadwerkelijke bitmapgegevens, maar is een weergaveobject dat de bitmapgegevens op het scherm weergeeft. Om het als een analogie te beschrijven: een Bitmap-instantie is als een diaprojector die wordt gebruikt om fotodia's op een scherm weer te geven en een BitmapData-object is als de fotodia die met behulp van een diaprojector kan worden weergegeven. Er kan direct een filter op een object BitmapData worden toegepast. Dit kan worden vergeleken met het direct tekenen op een fotografische dia om de afbeelding te veranderen. Een filter kan ook op om het even welk weergaveobject worden toegepast, inclusief een instantie Bitmap. Dit kan worden vergeleken met het plaatsen van een filter voor de lens van de diaprojector om de uitvoer op het scherm te vervormen (zonder de oorspronkelijke dia te wijzigen). Omdat de onbewerkte bitmapgegevens benaderbaar zijn via de eigenschap bitmapData van de instantie Bitmap, zou het filter direct kunnen zijn toegepast op de onbewerkte bitmapgegevens. In dit geval is het echter zinniger het filter op het weergaveobject Bitmap toe te passen in plaats van op de bitmapgegevens.

Zie Weergaveobjecten filteren voor meer informatie over het gebruik van het verschuivingskaartfilter in ActionScript.

Bitmapafbeelding maken door pixelwaarden in te stellen

Een belangrijk aspect van een verschuivingskaartfilter is dat het twee afbeeldingen nodig heeft. Eén afbeelding, de bronafbeelding, is de afbeelding die wordt gewijzigd door het filter. In dit voorbeeld is de bronafbeelding de instantie Bitmap met de naam sphere. De andere afbeelding die door het filter wordt gebruikt, is de kaartafbeelding. De kaartafbeelding wordt niet op het scherm weergegeven. In plaats daarvan wordt de kleur van elke pixel ervan gebruikt als invoer voor de verschuivingsfunctie; de kleur van de pixel op een bepaalde x-, y-coördinaat in de kaartafbeelding bepaalt hoeveel verschuiving (fysieke positieverschuiving) wordt toegepast op de pixel op die x-, y-coördinaat in de bronafbeelding.

Als gevolg hiervan heeft het voorbeeld de juiste kaartafbeelding nodig om het verschuivingskaartfilter te kunnen gebruiken voor het creëren van een bolvormig effect: een afbeelding met een grijze achtergrond en een cirkel die is gevuld met een enkele verlopende kleur (rood) die horizontaal van donker naar licht gaat, zoals hieronder wordt getoond:

Omdat slechts één kaartafbeelding en filter worden gebruikt in dit voorbeeld, wordt de kaartafbeelding slechts eenmaal gemaakt in de methode imageLoadComplete() (met andere woorden wanneer de externe afbeelding is geladen). De kaartafbeelding, fisheyeLens, wordt gemaakt door de methode createFisheyeMap() van de klasse MoonSphere aan te roepen:

var fisheyeLens:BitmapData = createFisheyeMap(radius);

Binnen de methode createFisheyeMap() wordt de kaartafbeelding met één pixel per keer getekend via de methode setPixel() van de klasse BitmapData. De volledige code voor de methode createFisheyeMap() wordt hieronder weergegeven, gevolgd door een stapsgewijze beschrijving van de werking ervan:

private function createFisheyeMap(radius:int):BitmapData 
{ 
    var diameter:int = 2 * radius; 
     
    var result:BitmapData = new BitmapData(diameter, 
                                        diameter, 
                                        false, 
                                        0x808080); 
     
    // Loop through the pixels in the image one by one 
    for (var i:int = 0; i < diameter; i++) 
    { 
        for (var j:int = 0; j < diameter; j++) 
        { 
            // Calculate the x and y distances of this pixel from 
            // the center of the circle (as a percentage of the radius). 
            var pctX:Number = (i - radius) / radius; 
            var pctY:Number = (j - radius) / radius; 
             
            // Calculate the linear distance of this pixel from 
            // the center of the circle (as a percentage of the radius). 
            var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY); 
             
            // If the current pixel is inside the circle, 
            // set its color. 
            if (pctDistance < 1) 
            { 
                // Calculate the appropriate color depending on the 
                // distance of this pixel from the center of the circle. 
                var red:int; 
                var green:int; 
                var blue:int; 
                var rgb:uint; 
                red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY)); 
                green = 0; 
                blue = 0; 
                rgb = (red << 16 | green << 8 | blue); 
                // Set the pixel to the calculated color. 
                result.setPixel(i, j, rgb); 
            } 
        } 
    } 
    return result; 
}

Op het moment dat de methode wordt aangeroepen, ontvangt deze een parameter, radius, die de straal aangeeft van de cirkelvormige afbeelding die moet worden gemaakt. Vervolgens maakt de code het object BitmapData waarop de cirkel wordt getekend. Dit object, result, wordt uiteindelijk doorgegeven als de geretourneerde waarde van de methode. Zoals wordt getoond in het volgende codefragment, wordt de BitmapData-instantie result gemaakt met een breedte en hoogte die net zo groot zijn als de diameter van de cirkel, zonder transparantie (false voor de derde parameter) en vooraf gevuld met de kleur 0x808080 (normaal grijs):

var result:BitmapData = new BitmapData(diameter, 
                                    diameter, 
                                    false, 
                                    0x808080);

Vervolgens gebruikt de code twee lussen om elke pixel van de afbeelding te doorlopen. De buitenste lus doorloopt elke kolom in de afbeelding van links naar rechts (de variabele i wordt gebruikt om de horizontale positie te vertegenwoordigen van de pixel die momenteel wordt gemanipuleerd), terwijl de binnenste lus elke pixel in de huidige kolom van boven naar beneden doorloopt (de variabele j vertegenwoordigt de verticale positie van de huidige pixel). De code voor de lussen (de inhoud van de binnenste lus is weggelaten) wordt hieronder getoond:

for (var i:int = 0; i < diameter; i++) 
{ 
    for (var j:int = 0; j < diameter; j++) 
    { 
        ... 
    } 
}

Terwijl de lussen de pixels één voor één doorlopen, wordt voor elke pixel een waarde (de kleurwaarde van die pixel in de kleurafbeelding) berekend. Dit proces omvat vier stappen:

  1. De code berekent de afstand van de huidige pixel tot het midden van de cirkel langs de x-as (i - straal). Die waarde wordt gedeeld door de straal om het een percentage van de straal te maken in plaats van een absolute afstand ((i - straal) / straal). Deze percentagewaarde wordt opgeslagen in een variabele met de naam pctX en de equivalente waarde voor de y-as wordt berekend en opgeslagen in de variabele pctY, zoals in de volgende code wordt getoond:

    var pctX:Number = (i - radius) / radius; 
    var pctY:Number = (j - radius) / radius;
  2. Met gebruikmaking van een trigonometrische standaardformule, de stelling van Pythagoras, wordt de lineaire afstand berekend tussen het midden van de cirkel en het huidige punt op basis van pctX en pctY. Die waarde wordt in een variabele met de naam pctDistance opgeslagen, zoals hieronder wordt getoond:

    var pctDistance:Number = Math.sqrt(pctX * pctX + pctY * pctY);
  3. Vervolgens controleert de code of het afstandspercentage minde dan 1 is (of 100% van de radius, met andere woorden als de pixel zich binnen de cirkelradius bevindt). Wanneer de pixel zich binnen de cirkel bevindt, krijgt deze een berekende kleurwaarde toegewezen (hier weggelaten, maar dit wordt later in stap 4 beschreven) en anders gebeurt er verder niets en wordt de pixelkleur niet gewijzigd, zodat de pixel normaalgrijs (standaard) blijft:

    if (pctDistance < 1) 
    { 
        ... 
    }
  4. Voor de pixels die zich binnen de cirkel bevinden, wordt een kleurwaarde berekend. De uiteindelijke kleur is een roodtint tussen zwart (0% rood) aan de linkerrand van de cirkel en helderrood (100%) aan de rechterrand van de cirkel. De kleurwaarde wordt oorspronkelijk berekend in drie delen (rood, groen en blauw), zoals hieronder wordt getoond:

    red = 128 * (1 + 0.75 * pctX * pctX * pctX / (1 - pctY * pctY)); 
    green = 0; 
    blue = 0;

    Alleen het rode deel van de kleur (de variabele red) heeft een waarde. De groene en blauwe waarden (de variabelen green en blue) worden hier ter verduidelijking getoond, maar kunnen worden weggelaten. Omdat het doel van deze methode het maken van een cirkel met een rood verloop is, zijn geen groene of blauwe waarden nodig.

    Zodra de drie afzonderlijke kleurwaarden zijn bepaald, worden deze tot een enkele kleurwaarde (geheel getal) gecombineerd via een bitschuivend standaardalgoritme, zoals in de volgende code wordt getoond:

    rgb = (red << 16 | green << 8 | blue);

    De berekende kleurwaarde wordt uiteindelijk toegewezen aan de huidige pixel met de methode setPixel() van het BitmapData-object result, zoals hieronder wordt getoond.

    result.setPixel(i, j, rgb);