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:
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 vcontext
kreslí pomocí cesty. - Cesta je oblouk, který má počátek ve středu kontextu, celkový úhel
2PI
a poloměrradius
. 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:
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 122x (1.98 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript