Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Navrhujeme doplněk webu v JavaScriptu

V tomto článku si zkusíme naprogramovat doplněk pro interaktivní stránky v JavaScriptu. Náš doplněk bude fungovat plně automaticky, tvořit budeme kulatý progress bar. K vykreslování použijeme canvas s data-* atributy. V tomto článku to nebudu uvádět step-by-step postupem, jak jste asi zvyklí, ale vždy vás pouze nakopnu (snad) správným směrem. Stejně tak článek počítá s tím, že jste studijní typy a dokážete použít google. I kdybyste nechtěli tvořit celý komplet, tak si můžete stáhnout přiložený zdrojový kód (dole pod článkem) a upravit ho tak, aby byl lepší a dokonalejší.

Někde se začít musí

Většina lidí začíná tím, že si představí výsledek. To je sice fajn, ale když pak začínají psát, pořád mají tu představu. Začněte jinak, představte si svůj výsledek, když jste jej ořezali na minimum. Toto se vám bude dělat mnohem lépe a té první představy dosáhnete mnohem rychleji. Stejně tak je dobré začít právě tím základem. Jestliže začnete vykreslováním textu doprostřed, při dodělávání samotného progress baru zjistíte, že to není až zas tak snadné a přitom je.

Začneme samotným skriptem, který bude obsluhovat každý canvas s atributem data-procent. K tomuto účelu nám dobře poslouží metoda document.query­SelectorAll(), která v parametru dostává CSS selektor a vrátí nám pole elementů, které by ovlivnil tento selektor. Pro vybrání všech canvasů s atributem data-procent použijeme selektor canvas[data-procent], po načtení stránky tedy projdeme pomocí querySelectorA­ll("canvas[da­ta-procent]"), který nám vrátí přesně ty canvasy co potřebujeme.

Nyní si vytvoříme objekt, který bude zastupovat náš kulatý progress bar. Objekty jsou v JavaScriptu jeden velký kámen úrazu. Definují se totiž konstruktorem, což je jednak už od pohledu divné, špatně se v tom orientuje a tím se nám občas i změní docela jasné proměnné i nabobtná pomocný kód. Nicméně se na objekty v JavaScriptu podívejme z té druhé stránky, jakmile by se naše progressbary rozrostly, projekt by se automaticky stal natolik složitý, že bez dobrého návrhu bychom se dříve nebo později dostali do bodu, kdy jsme na dosavadním projektu víceméně pouze ztratili čas. Ačkoli tedy s objekty ze začátku budeme zápasit, nebudeme se jim za žádnou cenu vyhýbat.

Objekt v JavaScriptu definujeme ve funkci, tam načteme všechny vlastnosti. Metody se definují přes prototype této třídy. Vlastnosti ukládáme přes klíčové slovo this. Jako jednoduchou ukázku kódu použijeme třídu pro osoby, na které to lze všechno docela pěkně vidět.

function Clovek(jmeno, vek) {
    this.jmeno = jmeno;
    this.vek = vek;

    Clovek.prototype.Pozdrav = function () {
        alert("Jmenuji se " + this.jmeno + " a je mi " + this.vek + " let.");
    }
}

var karel = new Clovek("Karel", 34)
karel.Pozdrav();

Zde vytváříme 34 letého Karla a necháme ho, aby nás pozdravil. V našem doplňku nám bude stačit jen jeden objekt, ten bude reprezentovat právě náš Progressbar. Objekt by mohl mít metody pro aktualizaci stavu a vykreslení, případně by mohl obsahovat metody pro vykreslování jednotlivých částí, čímž se kód zpřehlední. Jednotlivé metody a celkový kód nezapomeňte zdokumentovat, velmi vám to pomůže vyznat se v už tak dost nepřehledných objektech. Pro dokumentaci můžete použít třeba nějakou syntaxi, je jich hodně, můžete použít třeba JSdoc. Zápis JS doc se příliš neliší od dokumentace používané v Javě, naši metodu Pozdrav v člověkovi bychom mohli zdokumentovat následovně:

/**
 * @author Misaz
 * Představí člověka
*/
Clovek.prototype.Pozdrav = function () {
    alert("Jmenuji se " + this.jmeno + " a je mi " + this.vek + " let.");
}

Vykreslování

Vykreslování na plátno je zprostředkováno kontextem, na kterém se volají jednotlivé metody pro vykreslování. Budou vám bohatě stačit metoda arc(), která bere různé parametry a vykreslí část kruhu. Pozor si dávejte na to, že všechny úhly nejsou ve stupních, ale v radiánech. Vzorec pro převod stupňů na radiány je

Radiany = PI / 180 * stupně

Pokud převod budete používat častěji, vložte si to do funkce někde mimo. Velmi zajímavé je si tu funkci vložit přímo do interních Math. V JavaScriptu je to snadné, prostě přiřadíte do požadovaného názvu v Math (vytvoříte si nový, nic nepřepisujete) onu funkci. Tímto zakomponujete vaši funkci do již existujících a čistota kódu je zachována.

Math.deg2rad = function (degrades) {
    return Math.PI / 180 * degrades
}

Aby metoda arc() fungovala podle vašich potřeb, je potřeba si pohrát s cestami. Cestu otevřete metodou beginPath(), ukončíte closePath() a vykreslíte přes fill(). Ta vyplní uzavřenou cestu a stroke vykreslí pouze obrys.

Animace

Abyste docílili efektu animace, musíte v určitém intervalu volat vykreslování a aktualizaci stavu. K tomu můžete použít dvě varianty. Můžete nastavit interval nebo odpočet s tím, že odpočet byste pak museli v každém kroku nastavit nový. Na první pohled se může zdát, že interval je tedy lepší, ale opak je pravdou. Interval běží stále, i když není potřeba – animace přeci nebude nekonečná. Toto sice na běžném moderním počítači s obvykle 2 a více jádrovým procesorem nejde poznat, ale na mobilu se to výrazně negativně projeví na výdrži baterie (v dnešní době velký problém) a u některých telefonů i přehřívání (ale toho se většinou nevyhnete tak či tak). Osobně vám tedy s ohledem ke koncovému uživateli doporučuji metodu odpočtu, nastavíte ji metodou setTimeout(). Pokud jste se i přesto rozhodli pro interval, tak ten nastavíte přes metodu setInterval(). I pro interval je tu ještě jedna možnost, která by řešila problém zbytečných aktualizací a to návratovou hodnotu si někam uložit a v okamžiku konce animace zavolat clearIterval(), do parametru předáte právě proměnnou. Ve výsledku to může vyjít na stejno a je jen na vás, která varianta se vám více líbí.

Pokud jste animace v JavaScriptu nikdy nedělali a nejste v tom zběhlí, tak se vám možná budou na úvod hodit jednoduché tipy pro jejich tvorbu. Jestliže by se měl progressbar animovat, tak se bude hodnota většinu času pohybovat někde uvnitř. Nejprve to bude 0, pak 1, 2, 3 a nakonec to bude třeba 75 uložených v attributu data-procent (ten který jsme ověřovali selektorem). K zařazení této pohybující se proměnné do aplikace máte opět dvě varianty. První varianta je ta, že to budete celou dobu animace předávat v parametru, ta druhá, že si vytvoříte pomocnou proměnnou (osobně je pro přehlednost označuji tím, že začínají podtržítkem). Druhá mi osobně přijde o trochu lepší, protože dělali byste animaci, která může přibývat nebo ubývat (možná si říkáte na co ubývání, to proto, že jakmile implementuje obsluhu události pro změnu parametru, tak uživatel může zadat hodnotu menší než je dosavadní), tak musíte použít buď inkrementaci, nebo dekrementaci, ačkoliv to jde udělat všechno i v parametru přijde mi hezčí varianta pracovat s vlastností.

DOMsubtreeModified

Abychom mohli nějak za běhu kontrolovat změny parametrů, tak máme (jako už asi již tradičně) dvě možnosti. Ta první je, že budeme v určitém časovém intervalu kontrolovat každou hodnotu anebo si odchytíme událost DOMsubtreeModified. Ta se vyvolá vždy v okamžiku, když se cokoliv změní v stromu DOM. Ačkoli by tuto událost měli správně zpracovat všechny prohlížeče, zjistil jsem, že v Google Chrome nefunguje. Neustálá kontrola atributů je jednak asi mírně složitější, kód je méně přehlednější, jelikož tam je kolem toho spousta pomocného kódu a jak již jsem zmiňoval v odstavci o animacích, pro mobilní zařízení to není to pravé ořechové. Proto si odchyťte DOMsubtreeModified a obslužte si to podle libosti.

Možná vylepšení

Tímto byste měli mít progreessbary hotové a můžete se pustit do implementace dalších vylepšení, dbejte vždy na dobrý návrh, přemýšlejte a věřte, že přepisovat kód na pětkrát je zcela normální, někdy si to ani neuvědomujete. Nakonec vám vypíši, co byste mohli doimplementovat.

  • Volitelné animace, dejte možnost i neanimované verze, můžete použít attrbtu data-*
  • Možnost nastavování různých barev pro pozadí i samotný progress
  • Umožnit nastavení startovního úhlu, u některých aplikací se hodí víc když pregress začíná třeba v 3/5.
  • Podpora různé výšky šířky. Můžete třeba vycentrovat obsah, k tomu se dobře hodí možnost posunutí kontextu u plátna.

Doufám že se vám tento článek líbil, něco jste se přiučili, ale hlavně doufám že byl pro vás přínosný a vaše nadcházející výsledky v JavaScriptu budou zase o trochu lepší.

Zdrojákoviště JavaScript - OOP Doporučuji se zkoušet zapojovat do zdejších minisoutěží Machr na JavaScript. Trénujete nejen JavaScrit, ale i schopnost řešit určitou úlohu rychle a celý projekt stihnout dokončit do deadline. V Machru na JS se nehodnotí jenom výsledek, ale i zdrojový kód. A právě tento článek vás měl navést správnou cestou a dát vám některé tipy k správnému návrhu a psaní hezkého a dobře čitelného kódu. Právě kulatý progressbar je úloha jednoho předchozího machra. :)


 

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

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

 

Všechny články v sekci
Zdrojákoviště JavaScript - OOP
Článek pro vás napsal Michal Žůrek - misaz
Avatar
Uživatelské hodnocení:
6 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