Zarábaj až 6 000 € mesačne! Akreditované rekvalifikačné kurzy od 0 €. Viac informácií.

Analógové hodiny v JavaScripte

Možno by sa na vaše stránky hodili animované analógové hodiny. Ak poznáte JavaScript, nebude to veľký problém. Náš výtvor bude vyzerať nejako takto:

Analógové hodiny v JavaScripte - JavaScriptu zdrojákoviště - Základná konštrukcia jazyka

HTML 5 kostra

Najprv si predchystajú kostru HTML 5 dokumentu. Jediným dôležitým prvkom je práve 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

Pridáme základ nášho 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 vytiahneme <canvas> (plátno) podľa jeho identifikátora a kresliace kontext nastavíme práve z "plátna" na 2D.

Premenná radius, teda polomer, bude mať hodnotu polovice výšky kontextu. Väčšinou obrazovky bývajú širší ako vyšší. Počiatok kontextu presunieme do stredu plátna a polomer zmenšíme asi na 90%, to aby sa krásne zmestil rám hodín aj s rezervou.

Nakoniec budeme v intervaloch 1 sekundy volať funkciu, ktorá bude hodiny vykresľovať.

Vykresľovací funkcie

Teraz sa pozrieme na hlavné vykresľovací funkciu, ktorá v podstate volá funkcie pre kreslenie rámu hodín, ciferníka a ručičiek. Vlastne vykresľujú čas, pretože podľa neho sa potom kreslí ručičky. Tu toho k vysvetľovaniu veľa nebude:

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

Vykresľovací kód sme teda pre prehľadnosť rozdelili na 3 ďalšie funkcie, poďme si ich nad funkciou definovať.

drawFace()

Nasledujúce funkcie si bude žiadať trochu bližší pohľad, budeme si ju teda popisovať po častiach:

// ...
function drawFace(ctx, radius)
{
    ctx.beginPath();
    ctx.arc(0, 0, radius, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.fillStyle = 'white';
    ctx.fill();|
// ...
  • Pripravili sme si cestu pomocou beginPath(), pretože čiary a iné takéto veci sa v context kreslí pomocou cesty.
  • Cesta je oblúk, ktorý má počiatok v stredu kontexte, celkový uhol 2PI a polomer radius. Prečo práve 2pi snáď hovoriť ani nemusím, dúfam (uhol plného kruhu, pretože ciferník je kruh).
  • Nastavili sme bielu výplň, pretože sa môže stať, že hodiny niekto vloží na veľmi farebné pozadie a nebudú vidieť ani ručičky, ani čísla. Tým hodiny strácajú zmysle.
  • A celý kruh sme vybielili pomocou fill()

V ďalšej časti funkcie si pripravíme gradientný výplň rámu hodín a rovno ju aj nakreslíme.

Všimnite si, že všetky parametre udávame ako percentuálny časť polomere, čo je výborné, ak si hodiny budete chcieť zväčšiť alebo zmenšiť. Potom stačí len zmeniť veľkosť 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álne gradient má niekoľko argumentov - createRadialGradient(x_0, y_0, r_0, x_1, y_1, r_1). Pre os X je to počiatok v stredu a polomer (tu 95% polomeru)), pre os Y je polomer 105% polomeru.
  • Farebné nastavenie: od počiatku je šedá (skoro čierna) idúce do bielej a potom zas späť do šedej.
  • Štýl čiary nastavíme na náš gradient a silu čiary na 10% polomeru.
  • Posledný príkaz vykreslí nami nastavenú čiaru, idúce po ceste z predošlej časti funkcie.

Ešte urobíme takú malú bodku za hodinovým rámom, teda na ňom. A to presne uprostred, v mieste, odkiaľ budú vychádzať ručičky. Tu už toho tiež 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()

Teraz sa pustíme do ciferníku. Použijem arabské číslice, ale ak sa vám chce, urobte si napríklad rímske. To však budete potrebovať jedno pole navyše: ["I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX", "X", "XI", "XII"];. Kód metódy drawNumbers() je nasledovné:

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

Tu sme si len nastavili veľkosť fontu na 15% priemeru vykresľovanie pokiaľ možno v centre kontexte. Pridáme ďalšie 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 celkom jednoduchý. Cyklus beží od 1 do 12 a spočítame potrebný uhol, umiestnenie danej číslice na ciferníku. Počiatok súradníc kontexte o tento uhol otočíme, posunieme o 85% polomeru. Rotáciu os vrátime späť a nakreslíme číslo. Potom opäť počiatok súradnicovej sústavy otočíme a počiatok vrátime späť do pôvodnej pozície i smeru. Potom môžeme maľovať druhé číslo v ďalšej iterácii.

drawHand()

Podobne budeme maľovať aj ručičky. Funkciu odovzdáme kontext a uhol natočenia ručičky. Je to vlastne smer vektora a jeho veľkosť. Posledný parameter je šírka čiary:

//...
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á funkcia bude počítať smer ručičiek v závislosti na čase:

  • Hodinovú ručičku nastavíme na uhol celých hodín a pripočítame pomernej uhly minút a sekúnd (pretože chceme, aby ju neovplyvňoval len počet celých hodín).
  • Minútová ručička sa opraví o pomerný uhol ručičky sekundové.

Kód je nasledujúci:

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 ho vyskúšať a pochváliť sa krásnymi hodinami:

Tvoja stránka
localhost

Samozrejme, že zdrojový kód je priložený v archíve.


 

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 122x (1.98 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript

 

Všetky články v sekcii
JavaScriptu zdrojákoviště - Základná konštrukcia jazyka
Článok pre vás napísal Virlupus
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
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