2. díl - Dokončujeme zajímavé interaktivní menu v JavaScriptu

JavaScript Objektově orientované programování Dokončujeme zajímavé interaktivní menu v JavaScriptu

Unicorn College ONEbit hosting Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

V tomto pokračování JavaScript tutoriálu o tvorbě doplňku, který zinteraktivní menu na kulaté, script dosadí pozice podpoložek menu a nastaví skrývání a zobrazovaní podpoložek.

Sinus a Cosinus

Abychom zjistili pozici X a Y, musíme použít matematické operace sin a cos. Obě jsou v Math a obě počítají s radiány. K převodu stupňů na radiány se používá vzorec Math.PI / 180 * stupne. Pro tento účel si vytvoříme funkci kterou umístíme do Math. Tam takové funkce přece patří. JavaScript je natolik velkorysý, že si můžeme vždy dát cokoliv kamkoliv. Do Math si tedy zadefinujeme funkci deg2rad, která příjímá jediný parametr - stupně a vrací radiány.

Math.deg2rad = function (degrades) {
        return Math.PI / 180 * degrades
}
Goniometrické funkce v JavaScriptu

Goniometrické funkce použijeme tak, že nám cos(znamyUhel) vrátí hodnotu, kterou když vynásobíme s poloměrem a přičteme X středu. Tak dostaneme hodnotu X, na které bude naše podpoložka. Pro X je to podobné s tím rozdílem, že místo cos() použijeme sin(). Od X a Y ještě musíme odečíst poloviční velikost podpoložky. Celá metoda by mohla vypadat následovně:

RadialMenu.prototype.setPositions = function () {
        for (var i = 0; i < this.children.length; i++) {
                var menu = this.children[i]
                var degressBetweenSubItems = 360 / this.children.length

                var degress = (degressBetweenSubItems * i);

                var sin = Math.sin(Math.deg2rad(degress))
                var cos = Math.cos(Math.deg2rad(degress))
                var x = this.size / 2 + (cos * this.size / 2) - menu.size / 2;
                var y = this.size / 2 + (sin * this.size / 2) - menu.size / 2;


                menu.element.style.top = y + "px";
                menu.element.style.left = x + "px";
        }
}

Styly

Ačkoliv jsme všechny velikosti a pozice nastavili z JavaScriptu, některé věci je lepší dělat přes CSS. Do projektu si vložte styl a zalinkujte ho do HTML stránky. Protože se tento tutoriál nezabývá CSS, napsal jsem ho za vás. V zásadě se jen jedná o to, že nastavíme, aby se pozice nastavovaly absolutně. Pak samozřejmě ještě barvičky, písma a nějaká animace. Celý zdrojový kód stylu je zde.

nav[data-radial-menu] {
        margin-top:50px;
}
nav[data-radial-menu] ul li {
        background-color: rgb(255, 237, 139);
        border-radius: 100%;
        position:relative;
        display:table;
        float:left;
        text-align:center;
        margin-left:100px;
}
        nav[data-radial-menu] span {
                font-family:Calibri;
        }
        nav[data-radial-menu] a {
                color: black;
                text-decoration:none;
        }
        nav[data-radial-menu] ul li span {
                vertical-align:middle;
                display:table-cell;
                width: 100%;
        }
        nav[data-radial-menu] ul li ul {
                position:absolute;
                top:0;
                left:0;
        }
                nav[data-radial-menu] ul li ul li {
                        background-color: orange;
                        position: absolute;
                        display: table;
                        margin-left: 0;

                        -moz-animation-name: ViewSubItems;
                        -o-animation-name: ViewSubItems;
                        -webkit-animation-name: ViewSubItems;
                        animation-name: ViewSubItems;

                        -moz-animation-duration: 0.45s;
                        -o-animation-duration: 0.45s;
                        -webkit-animation-duration:     0.45s;
                        animation-duration:     0.45s;

                        -moz-animation-iteration-count: initial;
                        -o-animation-iteration-count: initial;
                        -webkit-animation-iteration-count: initial;
                        animation-iteration-count: initial;
                }
                        nav[data-radial-menu] ul li ul li span {
                                position: absolute;
                        }
@keyframes ViewSubItems {
        from {
                opacity:0;
        }

        to {
                opacity:1;
        }
}
@-webkit-keyframes ViewSubItems {
        from {
                opacity:0;
        }

        to {
                opacity:1;
        }
}
@-webkit-keyframes ViewSubItems {
        from {
                opacity:0;
        }

        to {
                opacity:1;
        }
}

Když si stránku vyzkoušíte, již to bude vypadat k světu. Aby to bylo zajímavější, ještě doprogramujeme pro zobrazování, skrývání a změnu těchto dvou stavů metody. Těm nastavíme události, aby ze začátku byly všechny podpoložky skryté a při kliknutí se zobrazily. Metoda HideChildren (přidejte si ji do prototypu) jednoduše projde všechny podpoložky a nastaví jim CSS vlastnost display na none. Metoda displayChildrens bude fungovat úplně stejně, jen nastaví CSS vlastnost display na block. Metoda displayOrHideChil­drens ověří, že je tam alespoň jeden člen (přesněji pokud není žádný, vyskočíme z metody pomocí return) a jinak ověřuje stav CSS vlastnosti display prvního elementu. Pokud je block, zavoláme hideChildrens, pokud ne, zavoláme displayChildrens.

RadialMenu.prototype.displayOrHideChildrens = function () {
        // numusí mít žádného člena
        if (this.children.length == 0)
                return;

        if (this.children[0].element.style.display == "none") {
                this.displayChildrens();
        } else {
                this.hideChildrens();
        }
}

No a finišujeme. V konstruktoru objektu RadialMenu nastavíme obsluhu události, která při kliknutí zavolá metodu displayOrHideChil­drens. Nakonec zavoláme metodu hideChildrens, která zajistí že po načtení budou podpoložky skryté.

Machr na JavaScript

Doufám, že se vám tento dvojdílný tutoriál líbil. Pokud si chcete dále procvičovat JavaScript, sledujte zdejší Machry na JavaScript. Právě toto je řešení jednoho z předchozích machrů. V machrech netrénujte jen práci v daném jazyku, ale i schopnost dokončit projekt do deadline a nemalou váhu při hodnocení bere v potaz i přehlednost zdrojového kódu.


 

Stáhnout

Staženo 480x (219.47 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Jak se ti líbí článek?
7 hlasů
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity (1)

 

 

Komentáře

Avatar
SteveXtreme
Člen
Avatar
SteveXtreme:23.3.2014 18:00

Spousta matiky, co :D Tak hlavně aby se v tom nováček nestratil. Palec nahoru, každopádně!

 
Odpovědět 23.3.2014 18:00
Avatar
Odpovídá na SteveXtreme
Michal Žůrek (misaz):23.3.2014 18:16

Jo je to matematika základní školy, ale máš recht. Moji spolužáci už jsou v tomto třeba úplně ztraceni.

Odpovědět  +1 23.3.2014 18:16
Nesnáším {}, proto se jim vyhýbám.
Avatar
alex
Člen
Avatar
alex:13.10.2014 17:23
RadialMenu.prototype.setPositions = function () {
        for (var i = 0; i < this.children.length; i++) {
                var menu = this.children[i]
                var degressBetweenSubItems = 360 / this.children.length

                var degress = (degressBetweenSubItems * i);

                var sin = Math.sin(Math.deg2rad(degress))
                var cos = Math.cos(Math.deg2rad(degress))
                var x = this.size / 2 + (cos * this.size / 2) - menu.size / 2;
                var y = this.size / 2 + (sin * this.size / 2) - menu.size / 2;


                menu.element.style.top = y + "px";
                menu.element.style.left = x + "px";
        }
}

preco je tam to

menu.element.style.top = y + "px";
      menu.element.style.left = x + "px";

Nestaci proste menu.style.top? aku funkciu tam plni to element?
nemalo by to byt skor

this.element.children[i].style //resp
 this.element.menu

?

Editováno 13.10.2014 17:26
 
Odpovědět 13.10.2014 17:23
Avatar
Odpovídá na alex
Michal Žůrek (misaz):13.10.2014 17:40

protože proměnná menu obsahuje jakoby to podmenu a this by mi vrátilo ten základ z kterého vycházím, ale to nechci - já chci jako by jeho potomky.

- menu // toto vrátí this
  - podmenu1 // toto procházím v cyklu
  - podmenu2 // toto taky
  - podmenu3 // toto taky

já tu proměnnou menu definuji abych nemusel pořád dokola opisovat this.children[i].

Odpovědět 13.10.2014 17:40
Nesnáším {}, proto se jim vyhýbám.
Avatar
alex
Člen
Avatar
Odpovídá na Michal Žůrek (misaz)
alex:13.10.2014 18:07

takze je to v podstate to iste ako

this.children[i].style.left
 
Odpovědět 13.10.2014 18:07
Avatar
Odpovídá na alex
Michal Žůrek (misaz):13.10.2014 18:08

jo tak vidíš snad co na 3 řádku té metody ukládám do menu.

Odpovědět 13.10.2014 18:08
Nesnáším {}, proto se jim vyhýbám.
Avatar
týpek
Člen
Avatar
týpek:20.8.2015 22:51

Čau, článek hodně dobrý, moc mi pomohl s objekty v JS. Sice moc nerozumím funkci setPositions() ale to pro mě není hlavní. Ještě přidám menší kód, kterým jsem si obohatil menu. Zastaví probublávání událostí po kliku na podpoložky a načítá/skrývá je postupně.

Postupně načítá/skrývá položky menu. Nesmíme zapomenout předat self jako argument funkce.

RadialMenu.prototype.displayOrHideChildrens = function(self) {
        // prodleva mezi obejevnim se polozek menu
        var time = 100;
        var status = '';

        // overujeme, zda je menu skryte ci nikoliv. Pote si do promenne status dosadime spravnou vlastnost
        (this.children[0].element.style.display == "none") ? (status = "block") : (status = "none");

        var i = 0;
        var childrenLength = this.children.length;

        var timer = setInterval(function() {
                var menu = self.children[i];
                if (i < childrenLength) {
                        menu.element.style.display = status;
                        i++;
                }
        }, 100)
}

Tady zastavuji probublávání. Vložíme třeba hned za událost onclick, kde voláme funkci displayOrHideChil­drens()

// zastavime bublani po kliku na podpolozky
for (var q = 0; q < this.children.length; q++) {
        this.children[q].element.onclick = function(e) {
                e.stopPropagation();
        }
}
 
Odpovědět  +1 20.8.2015 22:51
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 7 zpráv z 7.