Psst. EU dotace 85 % pro OSVČ a firmy lze nyní čerpat i na e-learning. Více informací
Aktuálně: Postihly zákazy tvou profesi? Poptávka po ajťácích prudce roste, využij halloweenské akce 80% výuky zdarma!
Python týden

Analogové hodiny v JavaScriptu

Možná by se na vaše stránky hodily animované analogové hodiny. Pokud znáte JavaScript, nebude to velký problém. Náš výtvor bude vypadat nějak takto:

Analogové hodiny v JavaScriptu

HTML 5 kostra

Prvně si předchystáme kostru HTML 5 dokumentu. Jediným důležitým prvkem je právě plátno: <canvas id="canvas" width="600" height="600"></canvas>:

<!DOCTYPE html>
<head>
    <title>Hodiny</title>
</head>

<body>
    <canvas id="canvas" width="600" height="600"></canvas>
    <script>
        <!-- Zde budou hodiny -->
    </script>
</body>
</html>

JavaScript

Přidáme základ našeho skriptu:

let canvas = document.getElementById("canvas");
let ctx = canvas.getContext("2d");
let radius = canvas.height / 2;
ctx.translate(radius, radius);
radius = radius * 0.90;
setInterval(drawClock, 1000);
// ...

Z dokumentu si vytáhneme <canvas> (plátno) podle jeho identifikátoru a kreslící kontext nastavíme právě z "plátna" na 2D.

Proměnná radius, tedy poloměr, bude mít hodnotu poloviny výšky kontextu. Většinou obrazovky bývají širší než vyšší. Počátek kontextu přesuneme do středu plátna a poloměr zmenšíme asi na 90%, to aby se krásně vešel rám hodin i s rezervou.

Nakonec budeme v intervalech 1 sekundy volat funkci, která bude hodiny vykreslovat.

Vykreslovací funkce

Tento výukový obsah pomáhají rozvíjet následující firmy, které dost možná hledají právě tebe!

Nyní se podíváme na hlavní vykreslovací funkci, která v podstatě volá funkce pro kreslení rámu hodin, ciferníku a ručiček. Vlastně vykreslujeme čas, protože podle něj se pak kreslí ručičky. Zde toho k vysvětlování moc nebude:

//...
function drawClock()
{
    drawFace(ctx, radius);
    drawNumbers(ctx, radius);
    drawTime(ctx, radius);
}
//...

Vykreslovací kód jsme tedy pro přehlednost rozdělili na 3 další funkce, pojďme si je nad funkcí definovat.

drawFace()

Nasledující funkce si bude žádat trochu bližší pohled, budeme si ji tedy popisovat po částech:

// ...
function drawFace(ctx, radius)
{
    ctx.beginPath();
    ctx.arc(0, 0, radius, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.fillStyle = 'white';
    ctx.fill();|
// ...
  • Připravili jsme si cestu pomocí beginPath(), protože čáry a jiné takové věci se v context kreslí pomocí cesty.
  • Cesta je oblouk, který má počátek ve středu kontextu, celkový úhel 2PI a poloměr radius. Proč právě 2PI snad říkat ani nemusím, doufám (úhel plného kruhu, protože ciferník je kruh).
  • Nastavili jsme bílou výplň, protože se může stát, že hodiny někdo vloží na hodně barevné pozadí a nebudou vidět ani ručičky, ani čísla. Tím hodiny pozbývají smyslu.
  • A celý kruh jsme vybělili pomocí fill()

V další části funkce si připravíme gradientní výplň rámu hodin a rovnou ji i nakreslíme.

Všimněte si, že všechny parametry udáváme jako procentuální část poloměru, což je výborné, pokud si hodiny budete chtít zvětšit nebo zmenšit. Potom stačí pouze změnit velikost plátna.

// ...
let grad = ctx.createRadialGradient(0, 0, radius * 0.95, 0, 0, radius * 1.05);
grad.addColorStop(0, '#333');
grad.addColorStop(0.5, 'white');
grad.addColorStop(1, '#333');
ctx.strokeStyle = grad;
ctx.lineWidth = radius*0.1;
ctx.stroke();
// ...
  • Radiální gradient má několik argumentů - createRadialGradient(x_0, y_0, r_0, x_1, y_1, r_1). Pro osu X je to počátek ve středu a poloměr (zde 95% poloměru)), pro osu Y je poloměr 105% poloměru.
  • Barevné nastavení: od počátku je šedá (skoro černá) jdoucí do bílé a pak zas zpět do šedé.
  • Styl čáry nastavíme na náš gradient a sílu čáry na 10% poloměru.
  • Poslední příkaz vykreslí námi nastavenou čáru, jdoucí po cestě z předešlé části funkce.

Ještě uděláme takovou malou tečku za hodinovým rámem, tedy na něm. A to přesně uprostřed, v místě, odkud budou vycházet ručičky. Zde už toho také k popisu moc nebude:

//...
ctx.beginPath();
ctx.arc(0, 0, radius * 0.1, 0, 2 * Math.PI);
ctx.closePath();
ctx.fillStyle = '#333';
ctx.fill();
//...
}

drawNumbers()

Nyní se pustíme do ciferníku. Použiji arabské číslice, ale pokud se vám chce, udělejte si třeba římské. To však budete potřebovat jedno pole navíc: ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"];. Kód metody drawNumbers() je následující:

//...
function drawNumbers(ctx, radius)
{
    let num;
    ctx.font = radius * 0.15 + "px arial";
    ctx.textBaseline = "middle";
    ctx.textAlign = "center";
//...

Zde jsme si jen nastavili velikost fontu na 15% průměru vykreslování pokud možno v centru kontextu. Přidáme další kód:

//...
for (num = 1; num < 13; num++) {
    let ang = num * Math.PI / 6;
    ctx.rotate(ang);
    ctx.translate(0, -radius * 0.85);
    ctx.rotate(-ang);
    ctx.fillText(num.toString(), 0, 0);
    ctx.rotate(ang);
    ctx.translate(0, radius * 0.85);
    ctx.rotate(-ang);
}
//...

Tento kód je celkem snadný. Cyklus běží od 1 do 12 a spočítáme potřebný úhel, umístění dané číslice na ciferníku. Počátek souřadnic kontextu o tento úhel otočíme, posuneme o 85% poloměru. Rotaci os vrátíme zpět a nakreslíme číslo. Poté opět počátek souřadnicové soustavy otočíme a počátek vrátíme zpět do původní pozice i směru. Pak můžeme malovat druhé číslo v další iteraci.

drawHand()

Podobně budeme malovat i ručičky. Funkci předáme kontext a úhel natočení ručičky. Je to vlastně směr vektoru a jeho velikost. Poslední parametr je šířka čáry:

//...
function drawHand(ctx, pos, length, width)
{
    ctx.lineWidth = width;
    ctx.lineCap = "round";
    ctx.beginPath();
    ctx.moveTo(0, 0);
    ctx.rotate(pos);
    ctx.lineTo(0, -length);
    ctx.stroke();
    ctx.rotate(-pos);
}
//...

drawTime()

Poslední funkce bude počítat směr ručiček v závislosti na čase:

  • Hodinovou ručičku nastavíme na úhel celých hodin a přičteme poměrné úhly minut a sekund (protože chceme, aby ji neovlivňoval jen počet celých hodin).
  • Minutová ručička se opraví o poměrný úhel ručičky sekundové.

Kód je následující:

function drawTime(ctx, radius)
{
    let now = new Date();
    let hour = now.getHours();
    let minute = now.getMinutes();
    let second = now.getSeconds();

    // ********** Hodinová ručička; délka = 50% poloměru
    hour = hour % 12

    // Je třeba zohlednit i posun pro minuty a sekundy
    hour = (hour * Math.PI / 6) + (minute * Math.PI / (6 * 60)) + (second * Math.PI / (360 * 60));
    drawHand(ctx, hour, radius*0.5, radius*0.07);

    // ********* Minuty; délka = 80% poloměru
    minute = (minute * Math.PI / 30) + (second * Math.PI / (30 * 60));
    drawHand(ctx, minute, radius*0.8, radius*0.07);

    // ********* Sekundy; délka = 90% poloměru
    second = (second * Math.PI / 30);
    drawHand(ctx, second, radius*0.9, radius*0.02);
}

Tak a máme celý skript. Můžete jej vyzkoušet a pochlubit se krásnými hodinami:

Your page
localhost

Samozřejmě, že zdrojový kód je přiložen v archivu.


 

Stáhnout

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

 

Všechny články v sekci
JavaScript zdrojákoviště - Základní konstrukce jazyka
Článek pro vás napsal Virlupus
Avatar
Jak se ti líbí článek?
Ještě nikdo nehodnotil, buď první!
Autor se věnuje webovým aplikacím a skladově-účetnímu softwaru. Snaží se uvést zpět PC-Fand v Javě i Pythonu. Lexiální analýze a parserování. Studuje fyziku na MFF UK. Učil IT na střední škole.
Aktivity (5)

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!