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í.

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 - JavaScript zdrojákoviště - Základní konstrukce jazyka

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

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:

Tvoje stránka
localhost

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


 

Stáhnout

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

Staženo 115x (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
Uživatelské hodnocení:
Ještě nikdo nehodnotil, buď první!
Autor se věnuje webovým aplikacím, skladově-účetnímu softwaru, 3D grafice, lexiální analýze a parserování. Studuje fyziku na MFF UK. Učil IT na střední škole.
Aktivity