LINUXSOFT.cz Přeskoč levou lištu
Uživatel: Heslo:  
   CZUKPL

> JAK na animované menu

V dnešním díle se podíváme na jednu z možných implementací animovaného menu nasazeného na stránkách babybox.cz. Byť je tato implementace nasazená v provozu, patří právě mezi ty, které osobně nedoporučuji. Nicméně zde bylo na výběr něco v javascriptu, co by zvládl i indexovací robot, nebo nějaký flash zmetek, volba byla tedy jasná.

18.3.2011 00:00 | Ondřej Tůma | Články autora | přečteno 7831×

Zadání

Zadavatel společně s grafickým studiem vymysleli vizuálně hezké, nicméně jak už to v praxi bývá, na webu obtížně realizovatelné animované menu. Celý systém funguje tak, že je nejprve nutno kliknout na jednu z položek v hlavního menu, ta se v několika krocích rozbalí do submenu a až následně jednotlivé části jsou odkazy na konkrétní stránky.

S lítostí musím konstatovat, že návštěvníci stránek bez podpory javascriptu mají prostě smůlu. Roboti jsou na tom o něco lépe díky výskytu obrázkové mapy, která sice není svázána s obrázkem, ale robotům to by ale nemělo činit potíže.

Optimalizace

Animované menu se v javascriptu implementuje docela jednoduše. Resp. prostě se v časovém intervalu mění obrázek, a to vytváří dojem animace. Problém ale vzniká v momentě, když těch obrázků je mnoho a nejsou dopředu načteny. Na strojích s pomalejším připojení k internetu a nakonec, ne jen tam, mohou vznikat nepříjemné prodlevy v načítání jednotlivých obrázků animace. Navíc se browser zbytečně ptá serveru vícekrát, v našem případě až 17krát.



Toho lze obejít jednoduchým trikem a to tak, že všechny obrázky se spojí do jednoho velkého. Pomocí stylů se pak zobrazí jen první snímek, část obrázku a při animaci se posouvá tento obrázek. V praxi to znamená že hned na počátku se načte jeden větší obrázek a při spuštění animace se již pracuje s tímto načteným obrázkem. Ve výsledku, ten jeden velký obrázek není přesně n-krát větší, protože většina obrázkových formátů obaluje samotná data ještě různými metadaty a ty jsou jen jedny. Navíc, v případě komprese většího množství dat je vyšší šance, že dojde k optimalizaci. Nakonec si ke každému obrázku můžeme připočíst obal v podobě tcp/ip, resp. http požadavku, a vedle „spolehlivosti” získáme ještě menší nároky na datový objem.

Samotná implementace

Jednotlivé animované části jsou implementované pomocí JAK třídy. Ta na vstupu dostane jenom informace o počtu kroků animace a název, ze kterého pak vygeneruje názvy ostatních html prvků. Samotný kód je docela jednoduchý, je to malinká funkce, která se stará o animaci a pak pár mechanismů, které spojují obrázkovou mapu s animovanou položkou menu.

Třída obsahuje navíc i jednu metodu, která není navěšená na žádnou událost, resp. toto navázání je zakomentované. Tuto metodu jsem použil pro snazší tvorbu obrázkové mapy.

Hurá kód

Do těla článku záměrně vkládám jen některé kousky kódu. Celý příklad je přiložen k článku jako zip archív.

<div id="menuA" class="item">
            <img id="menuA-img" src="http://zeropage.cz/menu_fake.png" alt=""/>
            <map name="menuA-map">
                <area id="menuA-A" shape="polygon" coords="9,93, 57,11, 74,7, 85,23, 65,61, 21,89, 9,93"
alt="Archív aktualit" href="http://zeropage.cz/?p=aktuality-archiv"/>
                <area id="menuA-B" shape="polygon" coords="21,89, 105,40, 118,48, 121,65, 80,90, 28,90, 21,89"
alt="Poslední měsíc" href="http://zeropage.cz/?p=aktuality-mesic"/>
                <area id="menuA-C" shape="polygon" coords="28,90, 127,90, 137,108, 128,123, 84,125, 30,95, 28,90"
alt="Poslední týden"href="http://zeropage.cz/?p=aktuality-tyden"/>
                <area id="menuA-D" shape="polygon" coords="30,95, 121,147, 122,166, 106,177, 67,157, 30,95"
alt="Novinka" href="http://zeropage.cz/?p=novinka"/>
            </map>
        </div>

V html je nutné vytvořit některé prvky jednotlivých animovaných položek. Pokusím se je ve zkratce popsat. Fake obrázek je průhledný obrázek sloužící k propojení s obrázkovou mapou. Toto propojení nastane až po rozbalení, aby se na odkazy nedalo kliknout pokud položka není rozbalená. [Právě toto by šlo upravit tak, aby mapa byla odebrána až javascriptem, pak by i návštěvníci bez javascriptu mohli klikat na odkazy, jen by je neviděli :(] Obrázková mapa definuje jak polygony jednotlivých položek animovaného menu, tak odkazy těchto položek. Celé je to uzavřené v divu. Ten má id, které je společným základem všech html prvků patřící právě k jedné skupině. To nám usnadní propojení s javascriptem.

Javascrtiptová třída MenuItem

Konstruktor třídy MenuItem, tedy jednoho animovaného submenu, obsahuje mimo jiných i tyto řádky:

    this.animateInterval = null;
    this.timeoutedClose = null;
    this.listeners = new Array();

    this._animate = this._animate.bind(this);
    this._timedClose = this._timedClose.bind(this);

    JAK.Events.addListener(this.dom, 'click', this, '_open');
    //JAK.Events.addListener(this.dom, 'mousemove', this, '_move');
    JAK.Events.addListener(this.dom, 'mouseout', this, '_close');

V kódu je navěšení metod na události animovaného menu. A hned pole listeners napovídá že jich bude víc než jen click a mouseout.

MenuItem.prototype._open = function(e, elm){
    pos = JAK.DOM.getPortBoxPosition(elm);
    elementX = Math.round(e.clientX - pos.left);
    elementY = Math.round(e.clientY - pos.top);
    if (elementX > 5 && elementX < 140 && elementY > 90 && elementY < 125){
        this.vertex = 1;
        if (!this.animateInterval)
            this.animateInterval = setInterval(this._animate, 50);
    } else {
        console.log('X: '+elementX);
        console.log('Y: '+elementY);
    }
}

Metoda _open, jak je z názvu a události na které je navěšená patrno, se stará o rozbalení jednoho menu. Protože ale zabalené menu je daleko menší než rozbalené, hlídá si tato metoda rozsah souřadnic, kde bylo kliknuto a tedy ohraničuje akci rozbalení jen na vymezenou oblast.

MenuItem.prototype._animate = function(){
    if (this.vertex == 1){   // otevirame
        this.dom.style.zIndex = 2;
        if (this.img == this.steps) {
            clearInterval(this.animateInterval);
            this.animateInterval = null;
            this._openAtEnd();
        } else
            this.img += 1;    
    } else {            // zavirame
        this._closeAtStart();
        if (this.img == 0){
            clearInterval(this.animateInterval);
            this.animateInterval = null;
            this.dom.style.zIndex = 1;
        } else
            this.img -= 1;
    }

    var s = ""+(this.img*-143) + "px 0px";
    this.dom.style.backgroundPosition = s;
}

Stěžejní metodou naší třídy je _animate. Ta se stará právě o požadovanou animaci. Jak je z kódu vidět, metoda detekuje směr nastavený metodami _open a_close a dle směru posune obrázek v pozadí. Tím vytváří efekt animace. Pokud byla animace dokončena, vymaže se naplánovaná akce - spuštění metody _animate. Navíc je v příhodném okamžiku puštěná další metoda _closeAtStart nebo _openAtEnd.

Tyto metody mají za úkol navázat, resp. odebrat obrázkovou mapu a příslušné metody s jednotlivými položkami rozbaleného menu. Protože při akci mouseout chceme, aby byl vybraný prvek označen.

MenuItem.prototype._overItem = function(e, elm){
    if (this.timeoutedClose != null){
        clearTimeout(this.timeoutedClose);
        this.timeoutedClose = null;
    }

    if (elm == this.domA)
        this.img = this.steps + 4;
    if (elm == this.domB)
        this.img = this.steps + 3;
    if (elm == this.domC)
        this.img = this.steps + 2;
    if (elm == this.domD)
        this.img = this.steps + 1;

    var s = ""+(this.img*-143) + "px 0px";
    this.dom.style.backgroundPosition = s;
}

Metoda _overItem provede změnu podobnou jako provádí metoda _animate. Metoda _over resetuje stav rozbaleného menu bez vybraného prvku. To proto, aby při zavírání nedošlo k nechtěným efektům.

Zajímavá je ještě metoda _close, ta ve skutečnosti menu nazavře, ale jen ono zavření načasuje. To proto mazání načasovaného zavření v metodách _over a _overItem.

Závěrem

Výše popsaný a k článku přiložený kód rozhodně není dokonalý a ještě by ho šlo o mnohé vylepšit. Je ale funkční a zadavatel získal přesně to co vyžadoval. Laskavého čtenáře tedy odkážu právě na přiložený příklad a jeho hlubší studii s tím, že kód dávám k volnému šíření a použití zdarma pod BSD licencí. Příště si ukážeme JAK se dá udělat vlastní scrollovací prvek.

Verze pro tisk

pridej.cz

 

DISKUZE

Nejsou žádné diskuzní příspěvky u dané položky.



Příspívat do diskuze mohou pouze registrovaní uživatelé.
> Vyhledávání software
> Vyhledávání článků

12.7.2016 13:14 /František Kučera
Spolek OpenAlt zve na 130. distribuovaný sraz příznivců svobodného softwaru a otevřených technologií (hardware, 3D tisk, SDR, DIY, makers…), který se bude konat ve čtvrtek 21. července od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

11.7.2016 16:53 /Redakce Linuxsoft.cz
Konference LinuxDays hledá přednášející. Přihlášky poběží do konce prázdnin, v září bude hlasování a program. Více na https://www.linuxdays.cz/2016/cfp/.
Přidat komentář

8.5.2016 17:19 /Redakce Linuxsoft.cz
PR: Dne 26.5.2016 proběhne v Praze konference Cloud computing v praxi. Tématy bude např. nejnovější trendy v oblasti cloudu a cloudových řešení, cloudové služby, infrastruktura cloudu, efektivní využití cloudu, možné nástrahy cloudů a jak se jim vyhnout
Přidat komentář

21.4.2016 8:01 /František Kučera
Spolek OpenAlt zve na 127. distribuovaný sraz příznivců svobodného softwaru a otevřených technologií (hardware, 3D tisk, SDR, DIY, makers…), který se bude konat ve čtvrtek 28. dubna od 18:00 v Radegastovně Perón (Stroupežnického 20, Praha 5).
Přidat komentář

2.3.2016 22:41 /Ondřej Čečák
Letošní ročník konference InstallFest již tento víkend!
Přidat komentář

14.2.2016 16:39 /Redakce Linuxsoft.cz
O víkendu 5. a 6. března 2016 proběhne na pražském Strahově 8. ročník tradiční konference InstallFest. Celkem za dva dny uvidíte ​30 přednášek​ a ​6 workshopů.
Přidat komentář

5.2.2016 17:38 /Petr Ježek
Utilitka z XFce "xfce4-power-manager" nejen umožňuje nastavení lhůty pro uspání či hybernaci, ale i zapínání a vypínání prezentačního módu pro nerušené sledování videí. Stačí ji nastavit v každém vybavenějším panelu a v jakémkoli nontiled WM/DE.
Přidat komentář

10.1.2016 11:32 /Pavel `Goldenfish' Kysilka
LinuxMarket změnil provozovatele. Nově jej provozuje Marek Pszczolka. Více info a detaily #1 a #2.
Přidat komentář

   Více ...   Přidat zprávičku

> Poslední diskuze

10.6.2016 21:10 / pavel riha
FreeBSD 10.3 a virtualizace

8.6.2016 21:56 / Milan Gallas
Nevalidní prefix m

7.5.2016 14:58 / Teodor Komárek
Soubory

20.4.2016 0:07 / Jakub Cleing
Sázkový panel PHP FUSION

9.4.2016 9:43 / jiwopene@gmail.com
Re: problém s dpkg a nemožností instalovat

Více ...

ISSN 1801-3805 | Provozovatel: Pavel Kysilka, IČ: 72868490 (2003-2016) | mail at linuxsoft dot cz | Design: www.megadesign.cz | Textová verze