Tvorba jednoduchého mapového prohlížeče ve ve FLASHI 1. První kroky Založíme si nový adresář (název a umístění může být libovolné). Vytvoříme nový projekt - v horním menu vybereme: File - New - Flash Dokument. Nastavíme velikost jeviště v Inspektor Property (Properties) na šířku 500px a výšku 400px. Obr.1. Následně vytvoříme tři základní vrstvy (pomocí tlačítka ): 1.vrstva: 2.vrstva: 3.vrstva: "aplikace - skripty" "aplikace - grafika" "data" POZOR!!! - řazení vrstev má svůj význam. Pokud by totiž byla vrstva "data" nad vrstvou "aplikace - grafika" zakryla by potom načtená mapa všechny objekty aplikace (tlačítka posunu i zoomování). Proto musíme dodržet výše uvedené řazení (také viz. obr.2) Obr.2. Na časovou osu vrstvy "aplikace - skripty" umístíme dva nové klíčové snímky. Klíčové snímky vložíme stiskem pravého tlačítka myši nad příslušným obdélníčkem na časové ose a následným výběrem "Insert Keyframe" (nad každým snímkem zvlášť - tedy nad druhým i třetím). U vrstev "aplikace - grafika" a "data" vložíme dva nové snímky pouze stiskem pravého tlačítka myši nad obdélníčkem třetího snímku časové osy a výběrem "Insert Frame". Soubor po celou dobu řešení průběžně ukládáme pod názvem "aplikace" do již vytvořeného adresáře na počátku práce!
2. Návrh grafického rozhraní aplikace Před vlastním kreslením si nastavíme uchopování na objekty a to pomocí View - snapping - snap to objects Pozn.: Podobně jako funkce ORTHO v AutoCADu tedy přichytávání k vodorovnému a svislému směru. Nyní se přepneme do vrstvy "aplikace - grafika". Nakreslíme pět obdélníků bez výplně - kdekoli mimo jeviště a jakkoli velké (viz Obr. 3.) postup: stisk tlačítka - Rectangle Tool nastavení kreslení bez výplně (No Color) Dále nakreslíme 5 linií - 3 vodorovné a 2 svislé - opět jakkoli umístěné a velké (viz Obr. 3.). postup: stisk tlačítka - Rectangle Tool Obr.3. Pro jednotlivé obdélníky a linie nyní nastavíme šířku, výšku a polohu X,Y jejich levého horního rohu. Jako první vždy vybereme grafiku a poté v Inspektor Property nastavíme hodnoty W, H, X, Y podle následující tabulky: 1. Obdélník: W = 500, H = 400, X = 0, Y = 0 1. Linie: W = 500, H = 0, X = 0, Y = 100 vodorovná 2. Obdélník: W = 450, H = 300, X = 25, Y = 25 2. Linie: W = 500, H = 0, X = 0, Y = 250 vodorovná 3. Obdélník: W = 50, H = 25, X = 165, Y = 360 3. Linie: W = 500, H = 0, X = 0, Y = 350 vodorovná 4. Obdélník: W = 50, H = 25, X = 225, Y = 360 4. Linie: W = 0, H = 400, X = 100, Y = 0 svislá 5. Obdélník: W = 50, H = 25, X = 285, Y = 360 5. Linie: W = 0, H = 400, X = 400, Y = 0 svislá
Následně vymažeme přebytečné linie (viz šipky na Obr. 4.) Obr.4. Obr.5. Všechny plochy, které budou využity jako tlačítka, vybarvíme pomocí nástroje Paint Bucket Tool a upravíme dle vlastního uvážení (viz červené šipky na obrázku č. 5). Mimo to vybarvíme také ještě podkladovou plochu dolního menu, která je na obrázku č.5 označena bílou šipkou. Výsledkem by měla být grafika obsahující objekty pro tlačítka posunu (8 směrů) a objekty pro tlačítka přibližování, oddalování a změny měřítka na původní měřítko. Vybarvíme podklad dolního menu (viz Obr.5.). 3. Převod grafiky na tlačítka Abychom mohli vytvořit tlačítko, potřebujeme k tomu grafiku, která jej bude reprezentovat. K tomu nám poslouží výplně, které jsme si vytvořili v předešlém kroku. Tedy vybereme vždy výplň a pomocí Modify - Convert to Symbol převedeme na tlačítko. V dialogovém okně "Convert to Symbol" potom zadáme název symbolu a v nabídce Behavior zvolíme možnost Button (viz Obr.6). Názvy jednotlivých symbolů jsou popsány na obrázku č. 7. Názvy tlačítek pro pohyb na jednotlivé světové strany: posunsz posuns posunsv posunv posunjv posunj posunjz posunz Názvy tlačítek pro změnu měřítka: plus minus puvodni Obr.6. Obr.7.
4. Úprava ostatní grafiky Jelikož při převodu grafiky na tlačítka došlo k zakrytí dělících linií, přesuneme tyto linie (včetně podkladové plochy dolního menu) do popředí a to následujícím způsobem. Vybereme všechny objekty na jevišti a následně s držením klávesy Shift klikneme na všechna vytvořená tlačítka - tím je vyloučíme z výběru. Zbylé prvky ve výběru převedeme na grafiku (Behavior - Graphic) a to opět pomocí Modify - Convert to Symbol s názvem "pomocne" (viz Obr.8). Obr.8. Obr.9. V posledním kroku grafické tvorby vytvoříme symbol pro umístění externích mapových dat. (Tento symbol by se dal vytvořit i pomocí action scriptu - avšak z praxe je zkušenost, že ne vždy takto vytvořený symbol pracuje správně, a proto bude lepší si jej vytvořit ručně.) Přepneme se tedy do vrstvy "data" a nakreslíme obdélník přibližně o velikosti 50x50 px opět mimo jeviště. Dále změníme jeho souřadnice na X = 250, Y = 175 (jeho levý horní roh = referenční bod - bude uprostřed mapového okna) a převedeme jej na symbol typu Movie Clip s názvem "mapa" (viz Obr. 9.). Pokud budeme potom vkládat externí data na scénu, nahradí se tento symbol vždy externí grafikou. 5. Popis instancí Jestliže chceme pracovat s grafikou na scéně pomocí action scriptu, bude třeba označit tuto grafiku tak, aby ji skript mohl jednoznačně identifikovat. K tomu nám poslouží tzv. název instance objektu. Samotná instance objektu (symbolu) je kopií originálního symbolu uloženého v knihovně. Pokud tedy vytvoříme např. pět instancí originálního symbolu, můžeme pro každou nastavit různou velikost, orientaci a dokonce i barvu - výhodou je, že fyzicky je na disku uložen pouze originál - z toho vyplývá velká úspora místa. Každá instance je potom označena jedinečným názvem, prostřednictvím kterého můžeme pomocí action scriptu zadávat instanci různé akce. Jediný objekt, se kterým budeme chtít pohybovat s pomocí action scriptu, bude instance symbolu "mapa". Klikneme tedy jednou na instanci symbolu "mapa" a v okně Inspektor Property napíšeme do pole Instance Name název instance "map".
6. Action Script Nyní se přepneme do vrstvy "aplikace - skripty" a vybereme první snímek na časové ose. Zápis skriptů bude probíhat v panelu Action-Frame. 6.1. PRVNÍ A DRUHÝ SNÍMEK Tab.1.: Action script prvního snímku //NAČTENÍ EXTERNÍCH SOUBORŮ map.loadmovie("mapka.swf",1); //KONTROLA NAČÍTÁNÍ - pokud je načítání dokončeno, spustit další akce function Nacitani(){ var Nacteno:Number=(map.getBytesLoaded()/map.getBytesTotal())*100; if(nacteno>=100){ Cas1=getTimer(); clearinterval(opakovani); gotoandstop(2); Opakovani=setInterval(Nacitani,10); stop(); Vysvětlení syntaxe - první snímek - část první - načtení externích souborů: Jako první bude třeba vložit externí soubor na scénu. To provedeme pomocí zápisu: map.loadmovie("mapka.swf",1); - instance symbolu "map", kterou jsme vytvořili na jevišti, se tímto příkazem nahradí externím objektem (v tomto případě souborem SWF - avšak může to být např. i obrázek JPG aj.) - externí objekt bude vložen tak, že jeho levý horní roh se umístí přesně na referenční bod - tedy na souřadnice středu snímku X = 250, Y = 175. - objekt bude umístěn do vertikální úrovně 1 Vysvětlení syntaxe - první snímek - část druhá - kontrola načítání: V druhé části napíšeme skript, který provede kontrolu načtení externího souboru. Tato kontrola je velice důležitá. Pokud by totiž nebyl externí soubor plně načten a chtěli bychom s ním hned provádět další operace, některé by se nemuseli provést nebo by se provedly špatně právě z důvodu jeho absence. Spuštění dalších snímků bude tedy provedeno až po jeho úplném načtení. Základem je funkce "Nacitani", která bude v pravidelných intervalech volána pomocí nastaveného intervalu "Opakovani". Obsahem funkce "Nacitani" musí být jednak samotný výpočet proměnné "Nacteno" obsahující hodnotu aktuálního počtu procent načtených dat a jednak podmínka "if(nacteno>=100)", která povolí další akce (zrušení intervalu a přesun na další snímek) až ve chvíli, kdy bude soubor plně načten.
Opakovani=setInterval(Nacitani,10); - jedná se o globální funkci, která nastavuje interval opakování jiné funkce - funkce "Nacitani" se spouští pomocí nastaveného intervalu "Opakovani" - frekvence obnovování se udává vždy v milisekundách - číslo 10 znamená, že funkce "Nacitani" bude volána každých 10 milisekund var Nacitani:Number=(map.getBytesLoaded()/map.getBytesTotal())*100; - lokální proměnná datového typu "Number", která udává míru načtení souboru (100 = plně načtený) - je to tedy podíl aktuální velikosti načtených dat ku celkové velikosti vynásobeno 100 (na procenta) map.getbytesloaded() - metoda getbytesloaded() vrací vždy aktuální hodnotu počtu načtených Bytů externího souboru map.getbytestotal() - metoda getbytesloaded() vrací hodnotu celkové velikosti externího souboru v Bytech if(nacteno>=100) - tato podmínka bude splněna, až se soubor plně načte (díky nastavenému intervalu bude podmínka každých 10 ms kontrolována až do chvíle, kdy bude výsledek proměnné Nacteno>=100) clearinterval(opakovani) - clearinterval() - vyčištění intervalu - po načtení již není třeba funkci "Opakovani" obnovovat - interval můžeme tedy již zrušit gotoandstop(2) - tento příkaz provede postup na druhý snímek Mimo podmínku "operace mohou být prováděny až po načtení dat" musíme myslet také na to, že počítání není vždy úplně přesné. Jelikož se tedy skutečné a počítané hodnoty nemusí rovnat (což je téměř vždy) musíme dodat ještě jistou časovou rezervu pro dokončení načítání dat. Provedeme tedy pozastavení přehrávání a to následujícím způsobem - do podmínky "if(nacteno>=100)" vložíme definici proměnné "Cas1". Jelikož chceme tuto proměnno použít i pro následující snímek, musíme ji definovat ne jako lokální, ale již jako globální tedy namísto "var Cas1:Number" pouze "Cas1". Cas1 = gettimer(); - globální proměnná, obsahující hodnotu získanou z funkce gettimer() gettimer(); - ve chvíli splnění podmínky "if(nacteno>=100)" vrátí v tomto případě funkce gettimer() aktuální hodnotu počtu milisekund, které uplynuly od spuštění movie clipu
Tab.2.: Action script druhého snímku //POZASTAVENÍ PŘEHRÁVÁNÍ function Pozastaveni(){ var Cas2:Number = gettimer(); var CasRozdil:Number = Cas2-Cas1; if(casrozdil>=500){ trace("hotovo"); clearinterval(opakovani2); gotoandstop(3); Opakovani2 = setinterval(pozastaveni,10); Vysvětlení syntaxe - druhý snímek - kontrola načítání: Pokud potom u druhého snímku v zápise AS zadáme interval "Opakovani2", který bude volat funkci "Pozastaveni" s proměnnou "Cas2" obsahující aktuální hodnotu gettimer(), můžeme pomocí podmínky "Cas2-Cas1>=500" pozastavit přehrávání na ½ sekundy. Tedy například pokud se snímek načte za 12500 ms, potom Cas1 = 12500. V tuto chvíli dojde k přesunu na druhý snímek, ve kterém nastavený interval bude stále dokola volat funkci "Pozastaveni" tak dlouho, dokud nebude hodnota proměnné Cas2 o ½ sekundy větší než hodnota proměnné Cas1. Až teprve poté dojde k přesunu na třetí snímek, který obsahuje nejdůležitější skripty - vycentrování, nastavení posunu a zoomování. var Cas2:Number = gettimer(); - lokální proměnná, obsahující hodnotu získanou z funkce gettimer() gettimer(); - po spuštění druhého snímku začne funkce gettimer() vracet aktuální hodnotu počtu milisekund, které uplynuly od spuštění movie clipu var CasRozdil:Number = Cas2-Cas1; - lokální proměnná, obsahující výsledek rozdílu hodnot proměnných Cas2 a Cas1 if(casrozdil>=500) - tato podmínka bude splněna, až bude rozdíl proměnných >=500 milisekundám trace("hotovo") - pokud je výše uvedená podmínka splněna, vypíše se v okně OPTION text "hotovo"
6.3. TŘETÍ SNÍMEK Skript třetího snímku rozdělíme tématicky na tři části: Část první (základní definice): var Sirka:Number = _level0.sir; var Vyska:Number = _level0.vys; map._x -= Sirka/2; map._y -= Vyska/2; var vychozix:number = map._x; var vychoziy:number = map._y; var Sirka:Number = _level0.sir; var Vyska:Number = _level0.vys; - nejprve definujeme proměnné "Sirka" a "Vyska" obě datového typu Number. Tyto údaje budou vzaty z externího SWF souboru kde jsou definovány jako "Sir" a "Vys" - tyto externí proměnné definují šířku a výšku mapy v její 100% velikosti map._x -= Sirka/2; map._y -= Vyska/2; - jelikož se grafika vložila na střed scény svým levým horním okrajem, bude potřeba provést ještě její vycentrování a to jejím posunem o polovinu šířky doleva a o polovinu výšky nahoru var vychozix:number = map._x; var vychoziy:number = map._y; - aby bylo možné vrátit obrázek po posunu a změnách měřítka do původní polohy, bude třeba hned na začátku vrátit údaje o výchozí poloze do proměnných "vychozix" a "vychoziy"
Část druhá - nastavení funkcí posunu pomocí kláves a ohraničujících tlačítek: //POSUN MAPY******************************************************************* function onkeydown() { if(key.isdown(key.up)){ map._y+=5; if(key.isdown(key.down)){ map._y-=5; if(key.isdown(key.left)){ map._x+=5; if(key.isdown(key.right)){ map._x-=5; Key.addListener(this); onkeydown(); //POSUN MAPY******************************************************************* function fces(){ map._y+=5; function fcej(){ map._y-=5; function fcez(){ map._x+=5; function fcev(){ map._x-=5; function fcesz(){ map._x+=5; map._y+=5; function fcesv(){ map._x-=5; map._y+=5; function fcejz(){ map._x+=5; map._y-=5; function fcejv(){ map._x-=5; map._y-=5; Druhá část bude obsahovat funkce provádějící posun mapy. Posun pomocí kláves: Funkce onkeydown() bude spuštěna vždy po stisknutí klávesy a to na základě nadefinovaného listeneru Key.addListener(this); onkeydown(); tedy jakéhosi "naslouchače", který čeká na Váš povel z klávesnice. Tento povel je potom možno uskutečnit stiskem kláves UP viz. funkce if(key.isdown(key.up)), DOWN viz. funkce if(key.isdown(key.down)), LEFT viz. funkce if(key.isdown(key.left)) a RIGHT viz. funkce if(key.isdown(key.right)) Posun pomocí ohraničujících tlačítek: Posun bude také možné provádět stiskem jednoho z osmi tlačítek přímo v aplikaci. K tom slouží funkce function fces()... function fcejv(). Samy osobě však tyto funkce stačit nebudou. Aby mohly být spuštěny, musíme je zavolat ze skriptu definovaného přímo u tlačítka. Klikneme tedy jednou na tlačítko (třeba na posun JIŽNÍ) a do pole pro zápis AS napíšeme: on(press){ Opakovani = setinterval(fcej, 30); on(release, releaseoutside){ clearinterval(opakovani);
Obdobně nastavíme další tlačítka on(press) - pří držení tlačítka "JÍT NA JIH" bude tedy po každých 30 milisekundách volána funkce "fcej", která posune snímek vždy o 5 pixelů na sever (stejně tak je tomu i u klasických mapových prohlížečů - abychom mohli jít na jih - musíme mapu posunout na sever) on(release, releaseoutside) - po uvolnění pravého tlačítka myši nad nebo mimo symbol tlačítka dojde ke zrušení intervalu "Opakovani" Část třetí - nastavení funkcí zoomování: //NASTAVENÍ KROKU ZOOMOVÁNÍ var krokzoom:number = 1.05;//násobek zvětšení či zmenšení //*********************ZOOMOVÁNÍ - EXTEND***************************** function fcepuvodni(){ map._xscale = 100; map._yscale = 100; map._x = vychozix; map._y = vychoziy; //*********************ZOOMOVÁNÍ - PLUS******************************* function fceplus(){ map._x += ((map._x - 250)/map._width)*((map._width*krokZOOM)-map._width); map._y += ((map._y - 200)/map._height)*((map._height*krokZOOM)-map._height); map._width *= krokzoom; map._height *= krokzoom; function fceminus(){ map._x -= ((map._x - 250)/map._width)*(map._width-(map._width/krokZOOM)); map._y -= ((map._y - 200)/map._height)*(map._height-(map._height/krokZOOM)); map._width /= krokzoom; map._height /= krokzoom; stop; Jako první nastavíme krok zoomování - tedy o jaký násobek se bude mapa zvětšovat či zmenšovat. var krokzoom:number = 1.05; - lokální proměnná udávající krok násobku změny měřítka Poté definujeme funkce přibližování, oddalování a změny měřítka na 100%. Abychom mohli tyto funkce spustit, musíme je opět zavolat ze skriptu definovaného přímo u tlačítka. Klikneme tedy jednou na tlačítko (třeba na ZVĚTŠENÍ) a do pole pro zápis AS napíšeme: on(press){ Opakovani = setinterval(fceplus, 30); on(release, releaseoutside){ clearinterval(opakovani); To stejné provedeme i pro tlačítka "minus"a "puvodni".
function fcepuvodni(){ map._xscale = 100; map._yscale = 100; map._x = vychozix; map._y = vychoziy; - funkce změní měřítko mapy na 100% a přesune ji na výchozí souřadnice function fceplus(){ map._x += ((map._x - 250)/map._width)*((map._width*krokZOOM)-map._width); map._y += ((map._y - 200)/map._height)*((map._height*krokZOOM)-map._height); map._width *= krokzoom; map._height *= krokzoom; - funkce spustí akci přibližování mapy (zvětšování o násobek 1,05) tak, aby zvětšování probíhalo vždy od středu mapového okna aplikace (proto se musí dynamicky měnit i souřadnice mapy) function fceminus(){ map._x -= ((map._x - 250)/map._width)*(map._width-(map._width/krokZOOM)); map._y -= ((map._y - 200)/map._height)*(map._height-(map._height/krokZOOM)); map._width /= krokzoom; map._height /= krokzoom; - funkce spustí akci oddalování mapy (zmenšování o násobek 1,05) tak, aby zmenšování probíhalo vždy do středu mapového okna aplikace Soubor průběžně ukládáme pod názvem "aplikace" do již vytvořeného adresáře na počátku práce! 7. VYTVOŘENÍ EXTERNÍHO SOUBORU Vytvoříme nový projekt - v horním menu vybereme: File - New - Flash Document Nastavíme velikost jeviště v Inspektor Property na šířku 2800px a výšku 2800px Pomocí File/Import/Import to Stage... vložíme na jeviště obrázek (menší než 2800x2800px) - Můžeme stáhnout z internetu rastrovou mapu nebo letecký snímek. Klikneme jednou na vložený obrázek a převedeme jej na symbol typu Movie Clip s název "Obrazek". Tím nám vznikne na ploše automaticky instance objektu, kterou nazveme "obr". Nakonec klikneme jednou mimo jeviště, tím deaktivujeme symbol, a v panelu Action-Frame napíšeme pro první snímek následující zápis: _root.sir = obr._width; _root.vys = obr._height; Nakonec dokument uložíme pod názvem "mapka" do stejného adresáře jako je uložený soubor aplikace.
8. TEST FUNKČNOSTI APLIKACE Z dokumentu mapka vygenerujeme SWF - v horním menu vybereme: Control/Test Movie. Nyní se vrátíme zpět k dokumentu aplikace a opět vybereme: Control/Test Movie. Pro testování provozu v určité rychlosti připojení nebudeme zavírat testovací okno a vybereme z horního menu: View/Download Settings požadovanou rychlost - poté klikneme na View/Simulate Download. Pro zobrazení v html vybereme ze základního menu File/Publish Preview/HTML Při zkoušení funkčnosti aplikace vždy nejprve vyzkoušíme tlačítka posunu a zoomování přímo v aplikaci a až teprve poté šipky posunu na klávesnici (klávesnice se totiž aktivuje, až když začneme pracovat s mapou pomocí myši).