Tvoříme zajímavé interaktivní menu v JavaScriptu
V tomto dvojdílném tutoriálu si zkusíme naprogramovat interaktivní menu v JavaScriptu. Naše menu bude kulaté a vysouvací. Položky vyskočí po okraji. Při programování se bude držet základu, že nebude nijak zasahovat do HTML návrhu menu. Naše menu v HTML bude velmi jednoduše seznam s položkami.

Jako ukázku si uděláme menu s třemi položkami, přitom interaktivní budou jen dvě. Struktura menu by mohla být následující.
- Web
- HTML
- CSS
- JS
- PHP
- SQL
- ASP.NET
- Programování
- C#
- Java
- VB
- Telefony
- C++
- Fórum
HTML našeho menu by mohlo vypadat následovně.
<nav data-radial-menu> <ul> <li> <span><img src="images/web.png" alt="Web"/><br />Web</span> <ul> <li><span><a href="#html"><img src="images/html.png" alt="html" /><br />HTML</a></span></li> <li><span><a href="#css"><img src="images/css.png" alt="css" /><br />CSS</a></span></li> <li><span><a href="#js"><img src="images/js.png" alt="js" /><br />JavaScript</a></span></li> <li><span><a href="#php"><img src="images/php.png" alt="php" /><br />PHP</a></span></li> <li><span><a href="#sql"><img src="images/sql.png" alt="sql" /><br />SQL</a></span></li> <li><span><a href="#asp"><img src="images/asp.png" alt="asp" /><br />ASP.NET</a></span></li> </ul> </li> <li> <span><img src="images/programing.png" alt="Programvání"/><br />Programování</span> <ul> <li><span><a href="#csharp"><img src="images/csharp.png" alt="C#" /><br />C#</a></span></li> <li><span><a href="#java"><img src="images/java.png" alt="Java" /><br />Java</a></span></li> <li><span><a href="#vb"><img src="images/vb.png" alt="Visual Basic" /><br />VB</a></span></li> <li><span><a href="#phones"><img src="images/phones.png" alt="Mobily" /><br />Mobily</a></span></li> <li><span><a href="#cpp"><img src="images/cpp.png" alt="C++" /><br />C++</a></span></li> </ul> </li> <li> <span><a href="#forum"><img src="images/forum.png" alt="Fórum" /><br />Fórum</a></span> </li> </ul> </nav>
Všimněte si, že jsem menu přidal attribut data-radial-menu. HTML5 nám povoluje definovat vlastní libovolný attribut, jen musí začínat data-*. Pomocí tohoto budeme označovat všechna menu, které následně v JavaScriptu zinteraktivníme. Do projektu si přidejte soubor JavaScriptu, který si v HTML naimportujte. V JavaScriptu si definujeme Objekt RadialMenu, který v konstruktoru bude přijímat jeden parametr – element. V tomto elementu budeme očekávat element nav, ve kterém je dále zakomponováno menu.
function RadialMenu(element) { }
Po načtení stránky (v obsluze události window.onload) získáme seznam všech elementů li, které jsou v ul a nav, který má nastavený atribut data-radial-menu. Toto provedeme pomocí metody querySelectorAll na document. Tato metoda přijímá jako první parametr textový řetězec s CSS selektorem a vrátí pole elementů, které těmto pravidlům vyhovují. CSS selektor pro výběr všech elementů, které mají nastavený atribut data-radial-menu bude postavený jednoduše z pravidla nav a do hranatých závorek dáme ten atribut dále pomocí porovnávací závorky (větší než) odkážeme na ul a li.
nav[data-radial-menu] > ul > li
Nyní vytvoříme nové instance našeho objektu RadialMenu pro každý element nav s atributem data-radial-menu. Všechny instance si dáme do pole, ať s nimi můžeme lépe pracovat.
var menuItems = new Array(); window.onload = function () { var navs = document.querySelectorAll("nav[data-radial-menu] > ul > li"); for (var i = 0; i < navs.length; i++) { menuItems.push(new RadialMenu(navs[i])) } }
Nyní se vraťme do konstruktoru a definujeme si několik proměnných, se kterými budeme pracovat:
var self = this this.element = element this.size; this.name = ""; this.children = new Array();
Hned na začátku máme self, do kterého si ukládáme this. Je to proto, že JavaScript si občas změní this a my se potřebujeme dostat k naší instanci (i když jsme třeba poskočili výš). Element je jasný, tam si ho uložíme. Velikost později dosadíme. Jméno se vždy hodí a potomci, tam dáme podpoložky.
Aby náš script podporoval různé velikosti, přidáme všem hlavním li (těm, které jsme získali pomocí querySelector) attribut data-size. Velikost submenu si script zjistí sám a to tak, že to bude přesně 25% z předka. V konstruktoru si jednoduše získáme hodnotu z attributu data-size. Pokud existuje, nastavíme ji výšce i šířce elementu. Šířku bychom celkem v bez problému nastavili i s pomocí CSS, ale výšku ne, protože nikdy nevíme, jaký poměr stran bude okno prohlížeče mít. CSS vlastnosti v JavaScriptu ovlivňujeme tak, že si vezmeme onen element, který má v objektu style všechny CSS vlastnosti. Lepší IDE vám s tím pomůže.
var datasize = this.element.getAttribute("data-size") if (datasize != null) { this.size = parseInt(this.element.getAttribute("data-size")) this.element.style.width = this.size + "px"; this.element.style.height = this.size + "px"; }
Nyní si projdeme všechny potomky našeho elementu. Potomci jsou uloženi v každém elementu ve vlastnosti childNodes, která je polem. Položky pole jsou pak další elementy.
for (var i = 0; i < this.element.childNodes.length; i++) {
Switchem rozebereme jaký název (nodeName) má náš potomek (ten, který procházíme cyklem). Celkem nás tam mohou potkat dva – span a ul. Span je název menu a ul je submenu. Pokud narazíme na span pouze jednoduše dosadíme name na hodnotu textContent tohoto elementu.
switch (this.element.childNodes[i].nodeName) { case "SPAN": this.name = this.element.childNodes[i].textContent; break; }
U ul to bude trochu složitější. V ul si budeme muset sehnat seznam li a ty zpracovat dále. Z každého li uděláme nový objekt RadialMenu a ten přidáme do pole children, kam dáváme submenu.
for (var u = 0; u < this.element.childNodes[i].childNodes.length; u++) { if (this.element.childNodes[i].childNodes[u].nodeName == "LI") { var menu = new RadialMenu(this.element.childNodes[i].childNodes[u]) this.children.push(menu) } }
Podpoložkám musíme nastavit velikosti. Na to si vytvoříme metodu SetSizes, metodu vytvoříme v prototypu za definicí objektu.
RadialMenu.prototype.SetSizes = function () {
V této metodě si projdeme všechny submenu a pokud nemají definovaný attribut data-size, nastavíme 25% velikosti z předka. Toto dosadíme do submenu.
RadialMenu.prototype.SetSizes = function () { for (var i = 0; i < this.children.length; i++) { var menu = this.children[i] var datasize = menu.element.getAttribute("data-size") if (datasize != null) { menu.size = menu.element.getAttribute("data-size"); } else { menu.size = this.size * 0.25 } menu.element.style.width = menu.size + "px"; menu.element.style.height = menu.size + "px"; } }
Metodu zavolejte po načtení submenu.
CSS neumí nijak dosazovat pozice kolem něčeho kulatého, tak si to musíme obsloužit sami. Vytvořte na prototypu objektu metodu SetPositions. Opět budeme proházet všechny submenu a každé umisťovat. Začneme tím, že si ujasníme, kolik stupňů bude mezi každou položkou, to jednoduše spočteme pomocí 360°/ početSubmenu. Dále si zjistíme, na jakých stupních bude položka menu otočena jednoduše pomocí i * stupnemezipolozkami.
Script je jen částečně hotový, příště (v pokračování) si napíšeme funkci setSizes, která podpoložky umístí kolem kruhu a jak podpoložky skrývat a zobrazovat.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 810x (219.47 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript