Lineær navigation i Adobe Flash

AttachmentSize
linear_navigation.zip66.41 KB

I denne artikel ser du en teknik til at løse lineær navigation i praksis. Her er tale om "nabo-metoden", der kan virke omstændig. Der findes nemmere (og hurtigere) metoder, men denne vil give dig en del fleksibilitet. Det giver dig også mere ActionScript 3.0 op under neglene - så det er nok ok givet ud ... den hurtige metode gemmer jeg til senere.

Inden du kaster dig ud i opgaven, bør du læse om lineær navigation på http://wiki.hjaelpmignu.dk/index.php?title=Metoder_til_lineær_navigation

Opgavefiler

For at følge denne tutorial skal du hente filen linear_navigation.zip (se vedhætede fil)

Vis filen du skal arbejde med

Opgavefilerne indeholder en række swf-filer (side1.swf til side5.swf) Det er de undersider du skal hente ind og kunne navigere frem og tilbage imellem. Derudover er der en fil, kaldet "start.fla". åbn den, da det er den, der skal gøre det ud for "hovedsiden" og hente alle de underliggende swf-filer ind og vise dem. Filen er bygget op med to knapper, der har fået navnene next_btn og prev_btn som instance name.

Opbyg et array med siderne
Stil dig i første frame på laget "Actions" og vis panelet Actions via Window>Actions F9 (Win) Option+F9 (Mac)
Det første du skal gøre er at danne et array (datasæt) der indeholder oplysninger om alle siderne, og deres relation til hinanden. Du bygger først ét array op kaldet pages. Derefter opretter du enkelte array's til hver side, med information om sidens titel, filnavn, samt nabo før og efter. Det ser således ud:

  1. var pages:Array = new Array();
  2. var side1:Array = ["side 1", "side1.swf", 0,2];
  3. var side2:Array = ["side 2", "side2.swf", 1,3];
  4. var side3:Array = ["side 3", "side3.swf", 2,4];
  5. var side4:Array = ["side 4", "side4.swf", 3,5];
  6. var side5:Array = ["side 5", "side5.swf", 4,0];
  7. pages.push(side1, side2, side3, side4, side5);
  8. var currentPage:int = 0;

En kort gennemgang, hvis du ikke har brugt array's før kommer her.

var pages:Array = new Array();

Først deklareres et objekt kaldet pages af typen Array. Array's gør det muligt at opbevare en række variabler i én container. Du vil kunne tilgå værdien af hver enkelt variabel ved at spørge efter det indeks, det blev placeret i. Dette array er som udgangspunkt tomt og klar til at fylde variabler i.

var side1:Array = ["side 1", "side1.swf", 0,2];

Et nyt array med navnet side1 bliver oprettet. Det bliver oprettet med en lidt hurtigere måde at deklarere et array objekt på. Hvor du normalt vil skrive var minvar:Array = new Array() kan du opnå samme effekt ve at skrive genvejen var minvar:Array = []. Den bliver fyldt med 4 værdier, der er et udtryk for sidens titel, filnavn, nabo før og nabo efter.

  1. var side2:Array = ["side2", "side2.swf", 1,3];
  2. var side3:Array = ["side3", "side3.swf", 2,4];
  3. var side4:Array = ["side4", "side4.swf", 3,5];
  4. var side5:Array = ["side5", "side5.swf", 4,0];

Mere af samme skuffe. Hver side får dets eget array, med det relevante indhold.

pages.push(side1, side2, side3, side4, side5);

Her bruges metoden Array.push() til at skubbe indhold ind i et array. pages er tomt fra starten af, så denne linje, vil indsætte sidernes array ind i det, ét ad gangen.

var currentPage:int = 0;

Endelig deklarerer du en variabel, der holder styr på, hvilken side, der i øjeblikket er den der vises.
Opret en beholder til de hentede sider

Det næste, du skal gøre, i klargøringsfasen er at oprette en beholder, der skal indhente alle de sider, der navigeres igennem.

  1. var container:Sprite = new Sprite();
  2. addChildAt(container, 0);

Først oprettes et sprite-objekt kaldet container, som derefter bliver indsat aller nederst i displaylisten. Her bruges addChildAt() med indeks 0, fordi der allerede er displayobjekter på listen. På denne måde sikres det at containeren til undersiderne placeres bag alt andet.

Vis den første underside når filmen starter
Det er vigtigt at side 1 er hentet ind når filmen starter, derfor skal du oprette funktioner, der varetager indhentning af swf-filer. Den deles i tre bidder. Lad os tage dem én ad gangen.

  1. function showPage(page:int):void
  2. {
  3. loadSubPage(pages[page][1]);
  4. }

Først kalder du en brugerdefineret funktion kaldet showPage() og overfører værdien af currentPage. Bagefter opretter du funktionen showPage() og kalder (som det eneste) en brugerdefineret funktion kaldet loadSubPage() med værdien af indeks 1 i den aktuelle sides array.

HUSK: Array's indeks starter fra 0. Når du bruger [1] svarer det til den anden værdi i array'et

  1. function loadSubPage(page:String)
  2. {
  3. var loader:Loader = new Loader();
  4. var url:URLRequest = new URLRequest(page);
  5. loader.load(url);
  6. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSubPageLoad);
  7. }

Denne funktion modtager filnavnet som en variabel kaldet page. En gennemgang af linjerne er følgende:

var loader:Loader = new Loader();

Først oprettes det loader objekt, der skal varetage indhentning af swf-filen.

var url:URLRequest = new URLRequest(page);

Du opretter defter et urlrequest-objekt, der indeholder navnet på filen, der skal hentes.

loader.load(url);

Endelig kaldes metoden Loader.load() der bruger urlrequest-objektet til at begynde hentning af filen.

loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSubPageLoad);

Alle udgaver af Loader klassen opretter også en udgave af LoaderInfo. Den kan tilgås med Loader.contentLoaderInfo og indeholder al information om det der hentes. Det er også den, der står for al håndtering af events i forbindelse med hentningen. Derfor er det også den, der skal have tilknyttet listeneren Event.COMPLETE. Så snart den affyres skal den kalde den brugerdefinerede funktion, onSubPageLoad()

  1. function onSubPageLoad(e:Event)
  2. {
  3. if(container.numChildren > 0)
  4. {
  5. container.removeChildAt(0);
  6. }
  7. container.addChild(e.target.content);
  8. }

I denne funktion foregår der to rutiner. Den ene rydder op, og den anden fylder nyt indhold i containeren, således:

  1. if(container.numChildren > 0)
  2. {
  3. container.removeChildAt(0);
  4. }

Funktionen onSubPageLoad() modtager et objekt fra loaderen. Den først if() løkke tester om der er nogle objekter i containeren - hvis der er det, bliver det fjernet.

TIP: Du ved, at der kun kommer ét objekt herind ad gangen. Er du i tvivl, og vil have fjernet flere kan du bruge en while() løkke.

container.addChild(e.target.content);

Den næste linje tager indholdet af content fra loaderen og overfører til objektet container. Alle loader objekter har en property kaldet content, som indeholder det, loaderen har hentet.

Få knapperne til at reagere og kalde siderne frem
Nu, hvor det er vist, at du rent faktisk kan få en underside hentet ind og vist (side 1), skal du få knapperne til at navigere imellem siderne. På den måde kan du bruge pilene til at flytte imellem de eksterne swf-filer.

For at få det til at virke, skal hver af knapper have en listener tilknyttet. De listener's skal øge og mindske currentPage med én og kalde showPage() med den opdaterede værdi af currentPage. Først den del af koden i sin helhed. Skriv følgende efter den anden kode (i frame 1):

  1. prev_btn.addEventListener(MouseEvent.CLICK, prevPage);
  2. next_btn.addEventListener(MouseEvent.CLICK, nextPage);

Start med at kigge på den ene event blok:

  1. prev_btn.addEventListener(MouseEvent.CLICK, prevPage);
  2.  
  3. function prevPage(e:MouseEvent):void
  4. {
  5. if(currentPage > 0)
  6. {
  7. currentPage--;
  8. showPage(currentPage);
  9. }
  10. }

Først tilknyttes en listener til prev_btn, der lytter efter MouseEvent.CLICK og kalder funktionen prevPage(). Inde i funktionen tjekkes der for, om currentPage er større end nul. Hvis den er det, udføres linjerne inde i if()-løkken. Inde i if()-løkken, formindskes currentPage først med én. Derefter kaldes showPage() funktionen så den nye side hentes og vises.

Samme procedure udføres i den anden blok. Den knyttes til next_btn og forhøjer currentPage med én. Den eneste store forskel er i if()-løkken, der ser sådan her ud:

if(currentPage < pages.length-1)

Her bruges pages.length-1. Denne værdi kommer frem sådan her. Array.length er en property, der indeholder antallet af elementer i arrayet. I dette tilfælde vil det give tallet fem (5). Array's starter fra nul (Innocent. Det betyder at tallet er nød til at blive korrigeret ned, med én (1) for at passe med araayet's indeks. Endelig testes der for at tallet er mindre end værdien. Dette gøres (i begge funktioner) for at værdien efterfølgende "har luft" til at blive én (1) større eller mindre.

Lidt hjælp til at navigere
Hvis du tester filmen, kan du se, at den virker efter hensigten. Noget, der dog springer i øjnene er, at du ikke (i knapperne) har en visuel indikator, der fortæller om du har ramt den ene eller anden ende af rækken. Et lille ekstra tjek, vil kunne løse det problem og give brugeren en bedre oplevelse. Koden ser således ud:

  1. function updateButtons():void
  2. {
  3. if(currentPage == 0)
  4. {
  5. prev_btn.removeEventListener(MouseEvent.CLICK, prevPage);
  6. prev_btn.enabled = false;
  7. prev_btn.alpha = 0.4;
  8. } else
  9. {
  10. prev_btn.addEventListener(MouseEvent.CLICK, prevPage);
  11. prev_btn.enabled = true;
  12. prev_btn.alpha = 1;
  13. }
  14.  
  15. if(currentPage == pages.length-1)
  16. {
  17. next_btn.removeEventListener(MouseEvent.CLICK, nextPage);
  18. next_btn.enabled = false;
  19. next_btn.alpha = 0.4;
  20. } else
  21. {
  22. next_btn.addEventListener(MouseEvent.CLICK, nextPage);
  23. next_btn.enabled = true;
  24. next_btn.alpha = 1;
  25. }
  26. }

Denne funktion tjekker om currentPage er i én af yderpositionerne og behandler knapperne, når/hvis det sker. Tag et kig på én af blokkene:

  1. if(currentPage == 0)
  2. {
  3. prev_btn.removeEventListener(MouseEvent.CLICK, prevPage);
  4. prev_btn.enabled = false;
  5. prev_btn.alpha = 0.4;
  6. } else
  7. {
  8. prev_btn.addEventListener(MouseEvent.CLICK, prevPage);
  9. prev_btn.enabled = true;
  10. prev_btn.alpha = 1;
  11. }

Her testes om den første side, er aktiv. Hvis det er tilfældet vil listeneren der er tilknyttet knappen prev_btn blive fjernet. Derefter vil selve knappen prev_btn blive deaktiveret, så musen ikke skifter til en hånd, når den kommer hen over den (prev_btn.enabled = false). For at understrege, at den ikke er aktiv, gøres den samtidig gennemsigtig (prev_btn.alpha = 0.4). Derefter kommer en else-klausul, der udføres hvis betingelsen ikke er opfyldt. Den aktiverer knappen og gør den ugennemsigtig.

Det samme kommer til at ske i den anden ende med den anden if()-løkke. Det kunne godt skrives sammen i én stor løkke (med else if() klausulen). Denne fremgangsmåde giver dog et lidt bedre overblik.

Nu skal denne løkke kaldes alle relevante steder fra. Det første sted er øverst, lige efter showPage(currentPage). De to andre steder er inde i if()-løkkerne i funktionerne prevPage() og nextPage(). Al koden ser sådan her ud i sin helhed:

TIP: Nu, hvor du har et tjek for første og sidste side i funktionen updateButtons() kan du godt fjerne den if()-løkke der omkranser kommandolinjerne i funktionerne. Det er nemlig ikke muligt mere, at klikke på en knap, hvis de er i yderste positioner mere.

  1. var pages:Array = new Array();
  2. var side1:Array = ["side 1", "side1.swf", 0,2];
  3. var side2:Array = ["side 2", "side2.swf", 1,3];
  4. var side3:Array = ["side 3", "side3.swf", 2,4];
  5. var side4:Array = ["side 4", "side4.swf", 3,5];
  6. var side5:Array = ["side 5", "side5.swf", 4,0];
  7. pages.push(side1, side2, side3, side4, side5);
  8. var currentPage:int = 0;
  9.  
  10.  
  11. var container:Sprite = new Sprite();
  12. addChildAt(container, 0);
  13.  
  14. prev_btn.addEventListener(MouseEvent.CLICK, prevPage);
  15. next_btn.addEventListener(MouseEvent.CLICK, nextPage);
  16. updateButtons();
  17. showPage(currentPage);
  18.  
  19. function prevPage(e:MouseEvent):void
  20. {
  21. if(currentPage > 0)
  22. {
  23. currentPage--;
  24. updateButtons();
  25. showPage(currentPage);
  26. }
  27. }
  28.  
  29. function nextPage(e:MouseEvent):void
  30. {
  31. if(currentPage < pages.length-1)
  32. {
  33. currentPage++;
  34. updateButtons();
  35. showPage(currentPage);
  36. }
  37. }
  38.  
  39. function updateButtons():void
  40. {
  41. if(currentPage == 0)
  42. {
  43. prev_btn.enabled = false;
  44. prev_btn.alpha = 0.4;
  45. } else
  46. {
  47. prev_btn.enabled = true;
  48. prev_btn.alpha = 1;
  49.  
  50. }
  51. if(currentPage == pages.length-1)
  52. {
  53. next_btn.enabled = false;
  54. next_btn.alpha = 0.4;
  55. } else
  56. {
  57. next_btn.enabled = true;
  58. next_btn.alpha = 1;
  59.  
  60. }
  61.  
  62. }
  63.  
  64. function showPage(page:int):void
  65. {
  66. loadSubPage(pages[page][1]);
  67. }
  68.  
  69. function loadSubPage(page:String)
  70. {
  71. var loader:Loader = new Loader();
  72.  
  73.  
  74. var url:URLRequest = new URLRequest(page);
  75. loader.load(url);
  76. loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onSubPageLoad);
  77. }
  78.  
  79. function onSubPageLoad(e:Event)
  80. {
  81. if(container.numChildren > 0) {
  82. container.removeChildAt(0);
  83. }
  84. container.addChild(e.target.content);
  85. }

Comments

Post new comment

  • Web page addresses and e-mail addresses turn into links automatically.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Lines and paragraphs break automatically.
  • You can enable syntax highlighting of source code with the following tags: <code>, <blockcode>, <as3>, <javascript>, <php>. The supported tag styles are: <foo>, [foo].
  • You may link to webpages through the weblinks registry
  • You may quote other posts using [quote] tags.
  • Textual smileys will be replaced with graphical ones.

More information about formatting options

CAPTCHA
Denne test er for at sikre at du er en reel bruger i stedet for en automatisk forespørgsel på en side. Spørgsmålet er for at undgå spam af sitet - tak for din forståelse
Image CAPTCHA
Enter the characters shown in the image.