. .. : Swf.hu 1.0 archívum : Swf.hu főoldal >>> : .. .




 
 
SEGÉDLETEK ActionScript

Interaktív flash tartalom mentése jpg fájlba
  feltöltve: 2006.11.03 | szerző: savanya | olvasva: 6575 alkalommal

   
 

Az itt következő segédlet a Flash8 új lehetőségeinek köszönhetően a címben jelzett problémára ad egy lehetséges megoldást. A segédletnek nem célja a benne szereplő flash, illetve PHP alapú kódok tágabb összefüggéseit magyarázni, kizárólag a végeredményhez szükséges, annak eléréséhez szorosan kapcsolódó technikákat fogjuk tárgyalni, ugyanakkor ahol erre lehetőség adódik, külső linkekkel jelezzük az éppen tárgyalt megoldásokat tágabb horizonton értelmező webhelyeket.

Legyen tehát a feladat egy olyan alkalmazás készítése, ahol a felhasználók egy meghatározott méretű rajzterületen pár egyszerű rajzi eszközzel maguk rajzolhassanak meg egy ábrát, majd azt JPG formátumban megjeleníthessék egy új popup ablakban (s onnan kezdve akár saját gépükre menthessék...).

A flash alapú kezelőfelület

Hozzunk létre egy új create_image.fla fájlt, amely tartalmaz:
- egy 100*100 pixel méretű fehér négyzet shape-et tartalmazó movie-clipet (mc) (instance neve: canvas_mc), ez lesz a rajzterület, ahova a felhasználók rajzolhatnak.
- 3 darab értelemszerű ábrával jelölt gombot - ezek lesznek hivatottak a rajzterületen alkalmazható rajzeszközöket aktiválni. Ez a 3 eszköz legyen: egy vonalhúzó (instance neve: line_btn), egy szabad-görbe rajzoló (instance neve: curve_btn) és egy szöveget beillesztő eszköz (instance neve: text_btn)
- egy színválasztó területet, ahol a felhasználó kiválaszthatja, hogy az adott eszközt milyen színben óhajtja használni. Ez is egy mc (instance neve: picker_mc), amely egy importált jpg képet tartalmaz, ezt kedvenc képszerkesztő programunkban tetszés szerint létrehozhatjuk.
- egy 'mentés' gomb, aminek megnyomására majdan a felhasználó elindíthatja a rajzolt ábrája képként való elmentésének folyamatát (instance neve: save_btn).
Körülbelül valami ilyesmi elrendezésben:

Mint az az ábrán is látszik, a canvas_mc egy vele megegyező méretű maszk alatt helyezkedik el (az ábrán csak piros körvonalával jelölve). Ennek oka, hogy mivel a felhasználók majd ebbe az mc-be fognak rajzolgatni, nem szeretnénk, hogy ezek a rajzolatok a megadott területen kívül is látsszanak. Így bármely, a későbbiekben a canvas_mc-be kerülő ábrarészletnek csak a megfelelő 100*100 pixeles területen lévő része fog látszani

Első lépésként jelöljük ki az Actions layeren levő frame-ünket, nyissuk meg az Actions palettát, és írjuk az alábbiakat, íly módon megadva néhány alapbeállítást, ami lényegében csak a majdani kész SWF fájlunk böngészőbeni helyes megjelenését hivatott kezelni:

// néhány alapbeállítás
Stage.scaleMode = "noScale";
Stage.showMenu = false;
_root._quality = "best";

A rajzolóeszközök funkcionalitásának megoldása:

Bár sokféleképpen megvalósítható a különböző rajzi elemek létrehozása, jelen esetben az elvi módszerünk az lesz, hogy minden egyes új rajzi elemet a canvas_mc-n belül új, üres mc-ben fogunk létrehozni a createEmptyMovieClip segítségével. Ezek elnevezéséhez létrehozunk egy drawingID nevű globális változót. Szükségünk lesz még egy másik penColor nevű globális változóra is, ebben fogjuk tárolni, hogy épp aktuálisan milyen színt választott a felhasználó a rajzoláshoz, egyelőre a feketét adjuk meg alapértelmezettként. És hogy ne tévesszük meg a felhasználókat, a rajzterületnek, mint gombnak nem engedjük meg, hogy a böngésző kéz-ikonja jelölje az aktív területét (ez természetesen opcionális). Továbbra is az első framen lévő kódunkat tehát folytassuk az alábbiakkal:

// globális változók, alapbeállítások
_global.penColor = 0x000000;
_global.drawingID = 0;
canvas_mc.useHandCursor = false;

Mindhárom rajzoló eszközre igaz, hogy megnyomásuk után a programnak 'tudnia kell', hogy a felhasználó pontosan mit is szeretne tenni a következőkben. Ami mindhárom esetében közös, hogy a felhasználó az adott eszköz használata során csak a rajterületre klikkelve tudja elkezdeni az adott műveletet. Ezt legegyszerűbben úgy tudjuk elérni, ha a rajzterületet, mint gombot kezeljük a továbbiakban, és az egyes rajzi eszközök megnyomásakor csak azt mondjuk meg, hogy mi is legyen az a funkció, ami a rajzlapra (canvas_mc) klikkelve le kell hogy fusson. Még mindig az első framen maradva folytassuk:

1.) A vonalat rajzoló eszköz:

// a vonal eszköz
line_btn.onRelease = function() {
      // a rajzlap fellett az egér bal gombjának lenyomására új, üres mc-t hozunk létre a canvas_mc-n belül(*11)
      canvas_mc.onPress = function() {
            drawingID++;
            this.createEmptyMovieClip("line"+drawingID, this.getNextHighestDepth());
            // ebbe az új, üres mc-ben fogjuk drawing apival megrajzolni a vonalunkat(*12)
            lineBeginX = this._xmouse;
            lineBeginY = this._ymouse;
            this.onMouseMove = function() {
                  this["line"+drawingID].clear();
                  //a vonaltipus meghatározásakor a szín értékét a globális penColor változóval adjuk meg(*13)
                  this["line"+drawingID].lineStyle(2, penColor);
                  this["line"+drawingID].moveTo(lineBeginX, lineBeginY);
                  this["line"+drawingID].lineTo(this._xmouse, this._ymouse);
                  updateAfterEvent();
            };
      };
      // az egérgomb felengedésre a vonal-rajzolást befejezzük(*14)
      canvas_mc.onRelease =canvas_mc.onReleaseOutside= function() {
            delete this.onMouseMove;
      };
};

Nézzük részletesebben:
*11 - az új, üres mc egyedi nevének meghatározásához növeljük a drawingID globális változó értékét eggyel. Mivel nem adjuk meg, hogy milyen pozícióba kerüljön ez az mc, így az a canvas_mc bal felső regisztráció pontjába kerül.
*12 - bevezetünk 2 új változót a drawing apival való rajzoláshoz (lineBeginX, lineBeginY) ezek hivatottak megjegyezni, hogy a felhasználó a kattintás pillanatában mely pozíciótól kezdi húzni a vonalat. A drawing api megértéséhez az ezirányú segédletek böngészését javaslom: 1. rész, 2. rész.
*13 - vonaltipusok meghatározásához lényegesen több paramétert is használhatunk Flash8-ban, mint a korábbi verziókban, kezdve az átlátszóságtól a végek lekerekítési módjának meghatározásán át a végeikkel éritkező vonalak csatlakozási módjáig (bővebben...)
*14 - hogy elkerüljük a rajzterületen kívül felengedett egérgombból fakadó esetleges bugokat, a a canvas_mc -nek mind az onRelease, mind az onReleaseOutside eseményekor töröljük a drawing api vonalrajzolásért felelős onMouseMove eseménykezelőjét.

2.) A görbét rajzoló eszköz:

// a szabad-görbe eszköz(*21)
curve_btn.onRelease = function() {
      canvas_mc.onPress = function() {
            drawingID++;
            this.createEmptyMovieClip("curve"+drawingID, this.getNextHighestDepth());
            this["curve"+drawingID].moveTo(this._xmouse, this._ymouse);
            this.onMouseMove = function() {
                  this["curve"+drawingID].lineStyle(6, penColor);
                  this["curve"+drawingID].lineTo(this._xmouse, this._ymouse);
                  updateAfterEvent();
            };
      };
      canvas_mc.onRelease = canvas_mc.onReleaseOutside=function () {
            delete this.onMouseMove;
      };
};

*21 - mint az könnyen észrevehető, a kód gyakorlatilag ugyanaz mint a vonalat rajzoló eszköznél, a két apró különbség, hogy a görbék számára létrehozott üres mc-k nevei nem 'line-nal', hanem 'curve'-vel kezdődnek (bár ennek különösebb jelentősége nincs), illetve maga a rajzolási módszer (és ismét: 1. rész, 2. rész ).

3.) A szövegbeíró eszköz:

// szövegbeíró eszköz
text_btn.onRelease = function() {
      // az canvas_ mc esetlegesen létező fölös gomb eseménykezelőit töröljük,
      // hogy véletlenül se okozhassanak galibát (*31)

      delete canvas_mc.onPress;
      delete canvas_mc.onReleaseOutside;
      canvas_mc.onRelease = function() {
            // a rajzlapon való klikkeléskor rögtön le is tiltjuk a rajzlap gombként való hazsnálhatóságát (*32-1)
            this.enabled = 0;
            txtFrmt = new TextFormat(); //dinamikusan létrehozott szövegmezők formázása (*33)
            //ismét a globális penColor változót használjuk a szöveg színének meghatározására
            txtFrmt.color = penColor;
            txtFrmt.size = 25;
            txtFrmt.font = "embeddedFont"; //(*33)
            drawingID++;
            // szövegbevitelnél azzal az apró módosítással élönk, hogy nem üres mc-t,
            // hanem üres szövegmezőt hozunk létre........
            this.createTextField("text"+drawingID, this.getNextHighestDepth(), this._xmouse, this._ymouse, 100, 25);
            this["text"+drawingID].embedFonts = true; //(*33)....
            this["text"+drawingID].type = "input";
            this["text"+drawingID].multiline = true;
            this["text"+drawingID].selectable = 1;
            this["text"+drawingID].text = " ";
            this["text"+drawingID].setTextFormat(txtFrmt); //....(*33)
            //........aminek rögtön át is adjuka fókuszt (megjelenik a villogó kurzor),
            // hogy a felhasználó lássa, hogy kezdhet írni. (*34)

            Selection.setFocus(this["text"+drawingID]);
            Selection.setSelection(0, 0);
            // némi szépészeti beavatkozás (*35)
            this["text"+drawingID].onChanged = function() {
                  this.text = this.text.toUpperCase();
                  this.autoSize = "left";
            };
            // amint a felhasználó 'kilép' a szövegmezőböl, azaz a szövegmezőröl lekerül a fókusz,
            // a canvas_mc ismét klikkelhető lesz, új szövegbeviteli lehetőségre készen (*32-2)

            this["text"+drawingID].onKillFocus = function() {
                  this.type = "dynamic";
                  this.selectable = 0;
                  this._parent.enabled = 1;
            };
       };
};

*31 - szövegbeviteli eszköz működése a vonal és görberajzolóhoz képest annyiban más, hogy nincs szükség a nyomvatartott egérgomb lekezelésére, így a felesleges gpmb eseménykezelőket érdemes törölni, és csak a klikkeléskor történő eseményre koncentrálunk a továbbiakban.
*32-1 - terv szerint amikor a felhasználó klikkelt a rajzterületen, megjelenik majd a villogó kurzor és megkezdődhet a szövegbevitel. a rajzlap klikkelhetőségét a a szövegmezőn lévő fókuszhoz viszonyítva fogjuk kezelni: - amíg a szövegmező aktív, addig a rajzlapon klikkelés nem hoz létre új szövegmezőt, mivel valószínűleg a user csak a bevitel végét jelzi a külső klikkeléssel (*32-2 ekkor a fókusz elvesztése révén a szövegmező egyben 'be is égetődik' a rajzba, tovább nem szerkeszthető (type = "dynamic", selectable = 0).
*33 - ez az a téma, amire itt és most egy szót sem vesztegetnék. Szövegmezők formázása saját propertyken keresztül, illetve textformattal, betűtípus beágyazása statikus, dynamikus módon, mind-mind csupa szép buktató (bővebben....)
*34 - a setFocus segítségével rögtön a frissen létrejött szövegmezőnek adhatjuk a fókuszt, míg a setSelection-nel megadhatjuk, hogy hol is villogjon a kurzorszár (illetve mely szövegszakasz legyen kijelölve) a szövegmezőn belül.
*35 - ez valóban csak szépészet és rendmánia - csak nagy betűvel írhatunk, és a szövegmező méretét mindig a tartalma méretéhez igazítjuk, minden olyan esetben, amikor a tartalom a felhasználó révén változik (Ezt hivatott figyelni az onChanged eseménykezelő.)

4.) A színválasztó eszköz:

// colorPicker színválasztás
picker_mc.useHandCursor = false;
//(*41)
picker_mc.onRelease = function() {
     
 // új BitmapData-t hozunk létre és ebbe 'bemásoljuk' a picker_mc-t (*42)
      pickerBitmap = new flash.display.BitmapData(80, 45, false, 0xFFFFFFFF);
      pickerBitmap.draw(this);
      
// a getPixel segítségével a klikkeléskor érvényes egérpozíciónak megfelelő
      // helyen levő pixel színértékeit tudjuk leolvasni (*43)

      hexCode = pickerBitmap.getPixel(this._xmouse, this._ymouse).toString(16);
      while (hexCode.length<6) {
            hexCode = "0"+hexCode;
      }
      _global.penColor = "0x"+hexCode;
      pickerBitmap.dispose();
};

*41 - az adott pixel lekérdezéséhez a picker_mc-t, mint gombot fogjuk használni, ám a falhasználói félreértések (és mert a kurzornyíl hegye pontosabb kiválasztást biztosíthat, mint a kéz-ikon mutatóujja), letiltjuk a kéz-ikon használatot.
*42 - ahhoz, hogy egy létező kép egy pixeljének színértékeit le tudjuk olvasni, szükségünk lesz a BitmapData osztály bizonyos metódusaira. az új Bitmapdata példány megadásakor annak méretét a picker_mc méretével azonosan veszzük fel, jelen esetben átlétszóságra nincs szükségünk, a háttér szine pedig lényegében indiferens, mivel a draw() metódussal a picker_mc képi megjelenését torzítatlan formában tudjuk a csak virtuálisan létező BitmapData példányunkba illeszteni (bővebben a BitMapDatáról..., és a draw() -ról... )
*43 - a getpixel() segítségével az épp aktuális _xmouse, _ymouse koordinátákon lévő pixel RGB adatait olvashatjuk le, Ahhoz, hogy ezt az értékez hexadecimális formában (RRGGBB) kapjuk meg, a toString(16) metódussal kell átkonvertánunk. Az így kapott hexCode változóval kapcsolatban még egy apró trükkre is szükségünk lesz, hogy ha a konverzió nem hat karakteres értéket ad vissza (mert a kezdő érték(ek) 0 értékűek), akkor ezeket egy while ciklusban pótoljuk. Ettől kezdve a globális penColor változónk ezt az új értéket tartalmazza, értelemszerűen a szükséges "0x" előtaggal.
Flash memória használati szempontból a már nem hazsnált virtuális BitmapDatánkat érdemes 'kiüríteni', ezt a dispose() metódussal tehetjük meg. (getpixel()..., dispose()... )

Eddig meg is volnánk, a rajzoló funkciók szépen működnek. Teszteljünk:

 
   
 
 

© Devnet.hu. A segédletek semmilyen formában nem másolhatók, publikálhatók a Devnet.hu és a szerzők közös írásos engedélye nélkül.
 
. .. : Swf.hu 1.0 archívum : Swf.hu főoldal >>> : .. .