[flash] tool / project: AS4 + XML

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Voor een intern project(je) wil ik een flash tool (flash CS4) ontwikkelen die vanuit een xml gegevens kan omzetten tot een grafische weergave. Abstract verhaal.
Concreet
code:
1
2
3
4
5
6
7
8
9
10
11
12
xml inhoud:

<blok1>
   <naam>Rood blok</naam>
   <hoogte>15mm</hoogte>
   <breedte>5mm</breedte>
</blok1>
<blok2>
   <naam>Groen blok</naam>
   <hoogte>13mm</hoogte>
   <breedte>3mm</breedte>
</blok2>


Wat ik wil is dat de flash applicatie een 2-tal dropdowns heeft waarin je 'blokken' kan selecteren die dan vervolgens voor je getekend worden zodat je visueel kan vergelijken.

De vraag is nu: ik heb duidelijk wat ik wil, ik heb ook het grafische ontwerp klaar, en de indeling van de xml (die natuurlijk vrij simpel is). Maar hoe pak ik dit logisch en effectief aan in flash? Mijn ActionScript kennis is van echt beginner niveau, ik zit wel vrij diep ik php.

Wat ik graag wil weten is: wat is een logisch beginpunt? Welke functie(s) zou(den) hiervoor het meest geschikt zijn?

Acties:
  • 0 Henk 'm!

  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
Ik zou sowieso eens beginnen je XML te structureren zodanig dat je niet nog allerlei zaken hoeft uit elkaar te gaan trekken (zoals het getal en de eenheid die nu in 1 waarde zitten):
XML:
1
2
3
4
5
6
7
8
9
10
<blok id="1">
   <naam>Rood blok</naam>
   <hoogte eenheid="mm">15</hoogte>
   <breedte eenheid="mm">5</breedte>
</blok>
<blok id="2">
   <naam>Groen blok</naam>
   <hoogte eenheid="mm">13</hoogte>
   <breedte eenheid="mm">3</breedte>
</blok>

(En dan nog liever in 't Engels). Dat maakt je leven alweer een stuk makkelijker. Daarbij gebruik je nu "generieke" blok-elementen; blok1 en blok2 zijn 2 verschillende soorten elementen terwijl ze exact hetzelfde bevatten en dus ook hetzelfde behandeld kunnen worden.

En persoonlijk had ik 't eerder zoiets gedaan:
XML:
1
2
3
4
<figures>
  <block id="1" name="Rood blok" width="15" height="15" unit="mm" color="#00f" />
  <block id="2" name="Groen blok" width="3" height="13" unit="mm" color="#0f0" />
</figures>

[ Voor 40% gewijzigd door RobIII op 09-05-2010 13:29 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
RobIII: dank je, ik pas de structuur daarop aan. Ik ga ervanuit dat de redenatie hierachter vooral is dat je gemakkelijker 'loops' kan opzetten door de meer gestandaardiseerde structuur? (even als php voorbeeld, een 'foreach' loop voor elke <block> in de xml.

Bedankt voor de tip, ik ga verder puzzelen met de nieuwe xml-structuur.

Als eerste stap heb ik ervoor gekozen om dropdowns te creëren die de namen uit de xml weergeven. Ik merk wel dat dit een stuk anders gaat dan dat ik het normaal met een html/php formulier zou hebben gedaan.

::edit::

Inmiddels de volgende tutorial erbij gevonden: http://www.flashandmath.com/howtos/loadxml/index.html

::edit 2::

Stukje bij stukje kom ik wat verder. Ik krijg het alleen niet voor elkaar om het aantal blocks in de xml te tellen, dit nummer heb ik nodig om een for loop te creëren. Wat ik nu heb ziet er zo uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// variabele aanmaken en definiëren als xml
var toestel_xml:XML;
// xml bestand inladen via urlloader
var inladen:URLLoader = new URLLoader();
inladen.load(new URLRequest("figures.xml"));
// controleren of xml volledig is ingeladen
inladen.addEventListener(Event.COMPLETE, verwerk_xml);
function verwerk_xml(e:Event):void 
        {
        figures_xml = new XML(e.target.data);

        //blocks in xml tellen
        var aantal:Array = new Array ('fiets','auto'); 
        for(var i=0; i<aantal.length; i++)
        {
        trace(toestel_xml.block[i].@name);
        trace(toestel_xml.block[i].@width);
        }
        }

In de test xml zitten 2 blocks in de root figures. Exact zoals RobIII had voorgesteld. Hoe tel ik het aantal blocks om de for loop automatisch te laten schalen met het aantal blocks? (met deze for loop wil ik een dropdown menu creëren waarmee de gebruiker 1 block uit alle blocks in de xml kan selecteren).

Het stukje 'fiets, auto' was om te proberen of ik de .length goed gebruik, door handmatig een array aan te maken werkt de for-loop prima. Als ik toestel_xml.length of var aantal = toestel_xml.toestel.length gebruik werkt het niet.

[ Voor 59% gewijzigd door murphsy op 09-05-2010 17:03 ]


Acties:
  • 0 Henk 'm!

  • Tsjilp
  • Registratie: November 2002
  • Niet online

Tsjilp

RS[I]ds

length is een methode, je moet dus xml.length() doen.

Raar... Is zo gek nog niet


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Ik had
code:
1
var aantal = figures_xml.length();

wel geprobeerd, maar hij geeft altijd het antwoord '1' op die methode. Ook al staan er 2 of meer 'childNodes' in de xml.

::edit::

Weer een dik uur stoeien later een nieuw probleem. Het tellen van het aantal childNodes in de xml werkt inmiddels prima. Evenals het aanroepen van specifieke attributen van specifieke childNodes en deze uitvoeren via een tekstveld. Bijv.: figures_xml.block[1].@width

Nu wil ik echter via een loop uitvoer voor elke childNode hebben en dit wil nog niet lukken. In de trace(blokken); geeft hij wel alle childNodes weer maar in de txt.text (uitvoer naar een tekstveld met de naam 'txt' pakt hij alleen de laatste childNode in de XML.

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function outputTekst():void
        {
        
        //blokken in xml tellen
        var aantal = figures_xml.block;
        
        //for loop die voor elk blok in de xml uitvoer maakt.
        for(var i=0; i<aantal.length();)
        {
        var namen:Array = new Array;    
        namen[i] = figures_xml.block[i].@name;
        i++;
        trace(namen);                                                                        < doet wel alle nodes
        }
        //output in 1 variabele stoppen om uitvoer mogelijk te maken
        var tekst = namen;  
        
        //output naar tekstveld sturen
        txt.text = tekst;                                                                      < doet alleen de laatste node
        }



De XML ziet er zo uit (versimpeld):
code:
1
2
3
4
5
6
<?xml version="1.0" ?>
<figures> 
  <block name="blok1" width="58" height="114" unit="mm"color="#00f" />
  <block name="blok2" width="62.1" height="115.5" unit="mm"color="#0f0" /> 
  <block name="blok3" width="52" height="107" unit="mm" color="#f00" /> 
</toestellen>


Ik wil de volgende output in het tekstvak met de naam 'txt':
blok1
blok2
blok3

Momenteel krijg ik echter deze output:
,,blok3

Zoals een waar gamer: 'episch gefaald!'

disclaimer
Excuses voor de vele vragen, ik ben een behoorlijke Flash newb (ten tijde van cs2 kon ik aardig uit de voeten) maar werk er wel hard aan om dit op een goede manier neer te zetten. Er is gelukkig geen haast bij.

Bedankt voor alle hulp!

[ Voor 84% gewijzigd door murphsy op 11-05-2010 15:29 . Reden: verder gewerkt en nieuwe inzichten ]


Acties:
  • 0 Henk 'm!

  • Tsjilp
  • Registratie: November 2002
  • Niet online

Tsjilp

RS[I]ds

murphsy schreef op dinsdag 11 mei 2010 @ 13:54:
Ik had

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function outputTekst():void
        {
        
        //blokken in xml tellen
        var aantal = figures_xml.block;
        
        //for loop die voor elk blok in de xml uitvoer maakt.
        for(var i=0; i<aantal.length();)
        {
        var namen:Array = new Array;    
        namen[i] = figures_xml.block[i].@name;
        i++;
        trace(namen);                                                                        < doet wel alle nodes
        }
        //output in 1 variabele stoppen om uitvoer mogelijk te maken
        var tekst = namen;  
        
        //output naar tekstveld sturen
        txt.text = tekst;                                                                      < doet alleen de laatste node
        }
Verdiep je eens in de AS syntax,

Je verhoogt de i in de forloop, terwijl je dat normaliter in de for() zelf doet (dus for(i=0; i < 5; i++))
In de forloop maak je steeds een nieuwe array namen aan, welke dus steeds maar 1 waarde zal bevatten,
je probeert een array in een tekstveld te zetten, hiervoor zul je de array eerst moeten omzetten naar een string (bijvoorbeeld met een join())

Raar... Is zo gek nog niet


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Tsjilp: bedankt voor de tips (heb op basis van keywoorden uit je reactie één en ander gevonden), maar je moet wel weten dat ik eigenlijk geen flash/actionscript programmeur ben. Meestal bevind ik me meer aan de concept kant van het ontwikkelproces maar ik vind het belangrijk om ook een beetje te weten hoe alles technisch in elkaar steekt. Dat voorkomt misverstanden en onmogelijkheden in het realisatietraject.

Dit is dus echt een hobby/zijprojectje voor mij. Ik hoopte er door middel van tutorials uit te komen, maar de flash tutorials vallen me erg tegen qua volgbaarheid. Daarom wendde ik mij tot het forum in de hoop samen met jullie door de AS3 heen te knokken :)

Nogmaals bedankt!

Acties:
  • 0 Henk 'm!

  • Marcvz
  • Registratie: April 2010
  • Laatst online: 09-07 12:35
Investeer in een lynda.com account en volg daar een as3.0 course. Lijkt me een stuk efficiënter.

D3 Profile (retired): D3 Armory
PoE Shop:Shop Twitch Stream:https://www.twitch.tv/marc_streaming


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Dankzij de erg hulpzame en motiverende reacties ben ik weer veel verder gekomen. [/sarcasme]

Maar ik ben wel degelijk veel verder gekomen door de hulp van Tsjilp. Omdat ik denk dat mogelijk anderen ooit iets aan dit topic zouden hebben en ik erop hoop dat er misschien nog wel een behulpzame tweaker rondloopt ga ik toch verder met dit topic.
Situatie nu
Ik heb inmiddels dropdowns (comboBox) die zichzelf vullen vanuit de xml, door middel van de addItem functie, dit ziet er zo uit:
code:
1
2
3
4
5
6
for(var i=0; i<aantal.length(); i++)
        {
        // voor elke childnode een item aanmaken in de combobox met de naam dropdown_cb

        dropdown_cb.addItem({label:figures_xml.block[i].@name, data:figures_xml.blocks[i].@id});
        }


Ook heb ik inmiddels uitgevogeld hoe ik vierkanten kan tekenen door middel van AS3 en dit gecombineerd met de data uit de xml:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function teken(){
        // vierkanten tekenen
        var breedte = figures_xml.block[1].@width;
        var hoogte = figures_xml.block[1].@height;
        trace(hoogte);
        trace(breedte);
        var vierkant:Sprite = new Sprite();
        addChild(vierkant);
        vierkant.graphics.lineStyle(1,0x222222);
        vierkant.graphics.beginFill(0xcccccc);
        vierkant.graphics.drawRect(0,0,-breedte,-hoogte);
        vierkant.graphics.endFill();
        vierkant.x = 475;
        vierkant.y = 350;
        }


Nu wil ik de teken() functie koppelen aan de combobox. Dit doe ik door middel van een eventListener.

code:
1
dropdown_cb.addEventListener(Event.CHANGE, teken);


Dit geeft echter een error! Ik heb ook dropdown_cb.addEventListener(Event.CHANGE, teken()); geprobeerd maar hij geeft hoe dan ook de error 'ArgumentError: Error #1063: Argument count mismatch on figures_tekenen_fla::MainTimeline/teken(). Expected 0, got 1.'.

Leuk detail is: deze error geeft ie pas weer zodra je iets selecteerd, de eventListener doet het dus in elk geval wel ;)

Mijn volgende vraag is dus: hoe koppel ik de teken() functie aan de comboBox dropdown?

Acties:
  • 0 Henk 'm!

  • Tsjilp
  • Registratie: November 2002
  • Niet online

Tsjilp

RS[I]ds

De error zegt het al:
Argument count mismatch on figures_tekenen_fla::MainTimeline/teken(). Expected 0, got 1

Oftewel: je functie (teken) verwacht 0 argumenten, maar de eventdispatchter geeft 1 argument (namelijk het event)

Raar... Is zo gek nog niet


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Ah, logisch. De evenListener geeft natuurlijk aan dat er wel/geen verandering heeft plaatsgevonden.

Wat ik wil bereiken is dat wanneer de comboBox verandert wordt de functie teken() geactiveerd wordt die op basis van het geselecteerde onderwerp uit de combobox het juist figuur tekent.

Dus ongeveer zo:

code:
1
2
3
4
5
6
7
8
*functies uit vorige posts die dropdowns maken

dropdown_cb.addEventListener( - verwijzing die ervoor zorgt dat de teken() functie geactiveerd wordt zodra er een figuur geselecteerd wordt uit de dropdown -);

function teken(){
 - selecteert op basis van de gemaakte selectie in de dropdown de juiste hoogte en breedte 
 * teken functie zoals eerder gepost
}


De laatste 2 knelpunten zijn dus de koppelen comboBox-verandering > tekenfunctie en tekenfunctie > juiste data uit xml halen.

Voor de juiste data ophalen denk ik aan een simpele oplossing, namelijk: elke block in de xml heeft een id-attribuut, dit id koppel ik als waarde aan de comboBox namen. vervolgens gebruikt ik de id om te verwijzen naar de juiste childNode, bijvoorbeeld:

Je selecteert 'vierkant', dit heeft id=2, vervolgens gebruikt ik dan figures_xml.block[id].@width als breedte, de id komt immers overeen met de [i] :)

::edit::

Duizend en één tutorials zeggen dat de volgende code zou moeten werken:

code:
1
2
3
4
5
6
7
8
9
10
//nieuw leeg object aanmaken op stage
var doeIets:Object = new Object();
//eventListener toevoegen aan combobox, verwijzen naar object
dropdown_cb.addEventListener("change", doeIets);
//functie toevoegen aan object
doeIets.change = function()
    {
    var lol = 10;
    trace(lol);
    }

Echter ik krijg dus de error:
"1118: Implicit coercion of a value with static type Object to a possibly unrelated type Function."

:: einde edit ::

Wat ik dus wil weten:
  • Hoe koppel ik teken() aan de comboBox?
  • Hoe geef ik teken() de geselecteerde id-waarde mee?

[ Voor 16% gewijzigd door murphsy op 22-05-2010 11:44 ]


Acties:
  • 0 Henk 'm!

  • WernerL
  • Registratie: December 2006
  • Laatst online: 14:26
Voor die dropdownbox kun je ook gewoon een MouseEvent.MOUSE_UP gebruiken toch? In de teken() functie de nieuwe value ophalen. Want volgens mij is er geen dropdown.VALUE_CHANGED event... :P

Flash ActionScript 3:
1
2
3
4
5
6
7
8
dropdownbox.addEventListener(MouseEvent.MOUSE_UP, teken);

function teken(e:MouseEvent):void
{
trace(dropdownbox.value);

//functie aanroepen die xml file uitleest? :+
}



Jouw voorbeeld hierboven werkt trouwens niet omdat er geen Event bestaat die "change" heet. Weet je zeker dat ze in die tutorial niet ook hebben gehad over het zelf programmeren van nieuwe Events?

//edit
En het ziet er as2-erig uit met doIets.change = function... je gebruikt toch wel gewoon AS3 he? ;)

[ Voor 28% gewijzigd door WernerL op 22-05-2010 12:44 ]

Roses are red, violets are blue, unexpected '{' on line 32.


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Haha. Jawel, het is wel AS3. Als ik jouw voorbeeld gebruik dan krijg ik een andere error (in elk geval geen knipperend beeld meer ;)), namelijk: 'ArgumentError: Error #1063: Argument count mismatch on toestel_afmetingen_fla::MainTimeline/doeIets(). Expected 0, got 1.'

Deze error verschijnt pas als ik de dropdown aanklik en de functie aangeroepen wordt dus.

Dezelfde dus als ik eerder kreeg. Hoe kan ik de functie zo maken dat hij wel een argument verwacht?

p.s. die change events heb ik uit ongeveer 6 verschillende AS3 tutorials :s

Acties:
  • 0 Henk 'm!

  • WernerL
  • Registratie: December 2006
  • Laatst online: 14:26
Je geet de functie doiets() een parameter mee die hij niet verwacht. Post je code dan nog eens die je tot nu toe hebt.

Roses are red, violets are blue, unexpected '{' on line 32.


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Okay :) komt ie.

Eerst het stuk dat de dropdown vult vanuit de xml

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
function outputTekst():void
        {
        
        //blokken in xml tellen
        var aantal = figures_xml.block;
        
        //for loop die voor elk blok in de xml uitvoer maakt.
        for(var i=0; i<aantal.length(); i++)
        {
        // voor elke een item (met als data de id) aanmaken in de combobox met de naam dropdown_cb
        dropdown_cb.addItem({label:toestel_xml.toestel[i].@name, data:toestel_xml.toestel[i].@id});
        }
                        
        }


Dan wil ik dus vervolgens een functie uitvoeren nadat de dropdown gebruikt is om een figuur te selecteren, stel we selecteren het figuur 'vierkant', dat ziet er zo uit in de xml:

code:
1
2
3
<figures> 
  <block id="1" name="Vierkant" width="15" height="15" unit="mm" color="#00f" /> 
</figures>


Ik probeer het detecteren van de selectie nu zo:

code:
1
2
3
4
5
6
dropdown_cb.addEventListener(MouseEvent.MOUSE_UP, doeIets);
function doeIets():void
    {
    trace(dropdown_cb.value);
        teken();
    }


Dit geeft echter een error! Ik heb het ook door middel van een object() geprobeerd, ook errors.

Vervolgens wil ik door middel van de functie teken() het daadwerkelijk figuur tekenen, ziet er momenteel zo uit:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function teken(){
        // juiste gegevens uit xml halen
        var id:Number = new Number();
        id = dropdown_cb.target.selectedItem.data;
        
        // vierkanten tekenen
        var breedte = figures_xml.block[id].@width;
        var hoogte = figures_xml.block[id].@height;
        trace(hoogte);
        trace(breedte);
        var vierkant:Sprite = new Sprite();
        addChild(vierkant);
        vierkant.graphics.lineStyle(1,0x222222);
        vierkant.graphics.beginFill(0xcccccc);
        vierkant.graphics.drawRect(0,0,-breedte,-hoogte);
        vierkant.graphics.endFill();
        vierkant.x = 475;
        vierkant.y = 350;
        }


Het stukje waarbij ik de id uit de dropdown wil halen en vervolgens wil gebruiken om hoogte en breedte te bepalen geeft ook errors. Als ik gewoon id = "1"; gebruik tekent hij een prachtig grijs vierkantje.

Alvast bedankt voor je tijd, ik ga er nog een kop koffie bij pakken ;)

Acties:
  • 0 Henk 'm!

  • WernerL
  • Registratie: December 2006
  • Laatst online: 14:26
Ok dit doe je fout:

function doeIets():void

ALLE functies die door de Eventhandler ge-dispatcht worden krijgen automatisch een Event object als parameter mee. Je moet de functie dus op deze manier declareren:

code:
1
function doeIets(e:MouseEvent):void { ... }
Het stukje waarbij ik de id uit de dropdown wil halen en vervolgens wil gebruiken om hoogte en breedte te bepalen geeft ook errors. Als ik gewoon id = "1"; gebruik tekent hij een prachtig grijs vierkantje.
Je weet dat je nu een String in een Number probeert te stoppen he? ;)

[ Voor 35% gewijzigd door WernerL op 22-05-2010 14:27 ]

Roses are red, violets are blue, unexpected '{' on line 32.


Acties:
  • 0 Henk 'm!

  • murphsy
  • Registratie: Januari 2009
  • Laatst online: 18-07 14:32

murphsy

Product Monkey

Topicstarter
Owhjee. Ik heb deze hele post maar even weggehaald. Want ik heb de fout gevonden :p

Blijkbaar een keertje teveel op backspace of ctrl+z gedrukt, er ontbrak ergens een... je raadt het al: argument. Fixed. Super bedankt voor de heldere uitleg Werner en Tsjilp.
Okay, ik heb de smaak te pakken dus we gaan door en maken het ons nog wat moeilijker
Ik heb nu:
  • Een functie die een dropdown maakt op basis van een xml
  • Een functie die vormen die je in de dropdown selecteert tekent
Maar dan wil ik eigenlijk ook nog:
  • De functie tekent nu de vormen steeds over elkaar heen, de daarvoor getekende vorm blijft gewoon staan. Ik wil maar één vorm tegelijk (per dropdown, zie volgende puntje)
  • Een tweede dropdown die ook figuren tekent (zou makkelijk moeten zijn)
  • De vormen klikbaar maken op basis van een url die in de xml staat
  • De naam van de vorm in de vorm weergeven (door middel van een automatisch aangemaakt dynamisch tekstveld)
First things first: eerst zorgen dat de oude vorm verdwijnt zodra er een nieuwe getekend wordt!

[ Voor 146% gewijzigd door murphsy op 22-05-2010 16:00 ]

Pagina: 1