Lekce 26 - Obrázky a kreslení na canvas v JavaScriptu
V minulé lekci, Práce s čísly a knihovna Math v JavaScriptu, jsme si představili si knihovnu
Math
pro práci s čísly.
V dnešním tutoriálu se začneme věnovat další
větší kapitole, práci s grafikou v
JavaScriptu. Ukážeme si, jak lze z kódu vkládat do
stránky obrázky reprezentované tagem <img>
a
představíme si tag <canvas>
(v překladu plátno). Na
plátno se pak naučíme nakreslit jednoduché geometrické
tvary.
Práce s obrázky
Klasický obrázek v HTML definujeme tagem
<img>
. Můžeme mu samozřejmě nastavit obsluhu
událostí, jako je kliknutí, a to úplně stejným způsobem jako
například u tlačítka.
V JavaScriptu obrázek vytvoříme jako jakýkoliv jiný element DOM zápisem:
let obrazek = document.createElement("img");
Stejného výsledku dosáhneme také zápisem:
let obrazek = new Image();
Tato varianta zároveň umožňuje nastavit obrázku rozměry. Požadovanou šířku a výšku obrázku v pixelech zadáme jako parametry v závorce:
let obrazek = new Image(100, 200); // 100 je šířka a 200 je výška
Aby se obrázek na stránce zobrazil, je ve všech případech
nutné jej nejprve vložit do dokumentu, například pomocí
document.body.appendChild(obrazek);
Načtení obrázku
Než s obrázkem začneme pracovat, musí se načíst.
Pokud máme obrázek v HTML a JavaScript spouštíme v obsluze události
onload
, není žádný problém. Prohlížeč zajistí, že náš
kód bude zavolán až poté, co se načte celá stránka.
V případě, že si obrázky vytváříme v JavaScriptu, musíme na načtení počkat:
let obrazek = new Image(); obrazek.src = "cesta/k/obrazku.jpg"; obrazek.onload = function () { // ... }
Použili jsme událost onload
na daném obrázku, a díky tomu
můžeme provádět všechny operace až ve chvíli, kdy víme, že obrázek je
načtený a připravený.
Další důležitou událostí při práci s obrázky je událost
onerror
, která je aktivována, když dojde k chybě při
načítání obrázku. Ke kódu výše doplníme:
obrazek.onerror = function() { console.error("Chyba při načítání obrázku: " + obrazek.src); };
V tomto příkladu se v případě chyby při načítání obrázku zobrazí v konzoli uvedený text. Obsluhu chyby lze ovšem upravit i rozšířit o další akce, jako je nastavení náhradního obrázku nebo výpis informace o chybě na stránce.
Ukažme si stejný kód s obsluhou událostí pomocí metody
addEventListener()
:
let obrazek = new Image(); obrazek.src = "cesta/k/obrazku.jpg"; obrazek.addEventListener('load', function() { console.log("Obrázek je načten a připraven k práci."); }); obrazek.addEventListener('error', function() { console.error("Chyba při načítání obrázku: " + obrazek.src); });
Všimněme si, že jsme událost načtení nenastavili jako
DOMContentLoaded
, ale jako load
. Takto ověříme, že
byly načteny i externí zdroje (jako například obrázky) a
ne pouze struktura HTML stránky, tedy všechny tagy DOM
elementů.
Přepínání obrázků
Pojďme si ukázat jednoduchý příklad, v němž budeme měnit obrázek na
stránce. Vytvoříme si přepínač. Po kliknutí na obrázek se zapnutým
přepínačem vložíme do stránky obrázek s vypnutým přepínačem a naopak.
Obrázky jsou ke stažení níže, pojmenujeme je prepinac0.png
a
prepinac1.png
a uložíme je do složky nového projektu:


Vytvoříme stránku, kde bude v <body>
obrázek s id
prepinac
a připojený skript z externího souboru
prepinac.js
. Jako výchozí obrázek použijeme
prepinac0.png
:
<!DOCTYPE html> <html lang="cs-cz"> <head> <meta charset="utf-8" /> <title>Přepínání obrázků</title> </head> <body> <img src="prepinac0.png" id="prepinac" alt="Přepínač" /> <script src="prepinac.js"></script> </body> </html>
Ve složce s projektem vytvoříme soubor prepinac.js
:
let prepinac; window.onload = function() { prepinac = document.getElementById("prepinac"); prepinac.onclick = prepni; }
V souboru jsme nejprve deklarovali proměnnou prepinac
a po
načtení stránky do ní uložili náš obrázek přepínače. Obrázku jsme
nastavili obsluhu události kliknutí, která spouští funkci
prepni()
. Tuto funkci si vzápětí doplníme.
Změna atributu src
Ve funkci prepni()
budeme potřebovat zjistit a změnit
aktuální hodnotu atributu src
našeho obrázku:
function prepni() { if (prepinac.getAttribute("src") == "prepinac0.png") { prepinac.src = "prepinac1.png"; } else { prepinac.src = "prepinac0.png"; } }
Tento atribut jsme získali pomocí metody getAttribute()
,
která vrací přesnou hodnotu uloženou v atributu. V
podmínce jsme ji poté porovnali s názvem jednoho z obrázků a následně
nastavili opačný obrázek.
Kdybychom v první části podmínky místo metody
getAttribute("src")
použili vlastnost src
a zapsali
prepinac.src
, získáme absolutní cestu k souboru s
obrázkem, například
https://www.priklad.cz/obrazky/muj-obrazek.jpg
.
Stránku si otevřeme a přepínač vyzkoušíme:
Plátno
Nyní si představíme plátno a ukážeme si, jak na něj kreslit. Plátno je vhodné použít pro případy, kdy potřebujeme vytvářet obrázky dynamicky, protože jeho obsah musíme definovat programově v JavaScriptu.
Plátno je reprezentováno párovým tagem <canvas>
. Tento
element musí mít nastavené atributy width
a
height
přímo v tagu <canvas>
. Pokud je
nezadáme nebo je definujeme pouze v CSS, může to vést k rozmazanému nebo
zkreslenému obsahu plátna v některých prohlížečích. Zatímco CSS mění
velikost zobrazení plátna, nepřizpůsobuje jeho vnitřní rozlišení.
Do těla nové HTML stránky tedy vložíme plátno takto:
<canvas width="500" height="500" id="platno"></canvas>
Získání kontextu plátna
Abychom mohli na plátno začít kreslit, musíme si získat jeho kontext. Kontext určuje, jaký typ obsahu budeme vytvářet. Existují různé typy kontextů, my se zaměříme na 2D kontext, který je ideální pro většinu grafických úloh.
Pro práci s 3D grafikou poskytuje JavaScript knihovnu WebGL (Web Graphics Library). My si jí však v tomto kurzu základů představovat nebudeme a zaměříme se pouze na práci s 2D kontextem.
Kontext plátna získáme voláním metody getContext()
:
let platno; let kontext; window.onload = function () { platno = document.getElementById("platno"); kontext = platno.getContext("2d"); }
Jako parametr jsme metodě předali formou textového řetězce typ
požadovaného kontextu, v našem případě 2d
. Na tomto
kontextu již můžeme volat různé metody pro kreslení.
Obdélníky
Základním objektem je obdélník. Obdélník nakreslíme pomocí metody
fillRect()
nebo strokeRect()
:
let platno; let kontext; window.onload = function () { platno = document.getElementById("platno"); kontext = platno.getContext("2d"); kontext.fillRect(50, 50, 100, 100); kontext.strokeRect(200, 50, 100, 100); }
Obě metody přijímají stejné argumenty. V prvních dvou zadáváme
souřadnice levého horního rohu obdélníku (x
a y
).
Pomocí dalších dvou argumentů nastavujeme výšku a šířku obdélníku
(width
a height
). Metoda fillRect()
obdélník vyplní, metoda strokeRect()
vykreslí pouze jeho
obrys.
Plnému čtverci jsme nastavili souřadnice x
a y
na hodnotu 50
, výšku a šířku jsme nastavili na
100
. Obrys čtverce má stejné hodnoty, pouze osa x
je posunuta na pozici 200
:
Čáry a trojúhelníky
Čáry se na plátno kreslí pomocí tzv. cest. Tyto cesty musíme začít a
uzavřít. Nejprve tedy voláme metodu beginPath()
, která
vytvoří novou cestu a přerušuje předchozí, pokud kreslíme více
nezávislých obrazců. Pro uzavření cesty zavoláme metodu
closePath()
.
Také v dalších příkladech musíme nejprve počkat na načtení dokumentu, poté získat element plátna z HTML souboru a nastavit mu kontext. V ukázkách však už budeme uvádět pouze kód pro kresbu jednotlivých geometrických tvarů.
Vykresleme si čáru z bodu [20;20]
do
[40;150]
:
kontext.beginPath(); kontext.moveTo(20, 20); kontext.lineTo(40, 150); kontext.closePath(); kontext.stroke();
Čáru jsme vytvořili pomocí metody lineTo()
. Čára se ve
výchozím nastavení vykreslí z pozice [0;0]
(levý horní roh
plátna), tuto pozici jsme proto změnili metodou moveTo()
. Metoda
sama o sobě nevykreslila nic, pouze přesunula kurzor plátna na zadanou
pozici. Obě uvedené metody přijímají parametry x
a
y
, tedy souřadnice pozice. Samotnou čáru jsme vykreslili metodou
stroke()
.
Přidáním druhé čáry pak vytvoříme obrázek trojúhelníku:
kontext.beginPath(); kontext.moveTo(120, 20); kontext.lineTo(140, 150); kontext.lineTo(200, 100); kontext.closePath(); kontext.stroke();
Je to proto, že při zavření cesty dochází k propojení výchozího bodu s konečným bodem.
Nyní můžeme použít také metodu fill()
:
kontext.beginPath(); kontext.moveTo(270, 20); kontext.lineTo(290, 150); kontext.lineTo(350, 100); kontext.closePath(); kontext.fill();
Metoda nám vyplnila vnitřek cesty barvou a vykreslila vyplněný trojúhelník:
Kruhy, kružnice a výseče
Další metodou pro kreslení na plátno je metoda arc()
. Ta
umí nakreslit kruh, kružnici a jejich výseče. Její syntaxe je
následující:
kontext.arc(x, y, polomer, pocatecniUhel, konecnyUhel, smer);
Každý úhel udáváme v radiánech. Plný
úhel je 2 * PI
, stupně se převedou na radiány jako
(PI / 180) * stupně
.
Kruh tedy nakreslíme takto:
kontext.beginPath(); kontext.arc(100, 100, 80, 0, Math.PI * 2); kontext.closePath(); kontext.fill();
Parametry x
a y
určují pozici
středu kruhu. Dále jsme uvedli jeho polomer
.
Následují parametry pocatecniUhel
a konecnyUhel
,
kterými určujeme, zda vykreslit celou kružnici nebo její výseč. Metodu
arc()
musíme používat uvnitř cesty.
Přidejme si ke stávajícímu příkladu ještě ukázku na vykreslení kružnice:
kontext.beginPath(); kontext.arc(300, 100, 80, 0, Math.PI * 2); kontext.closePath(); kontext.stroke();
V prohlížeči se zobrazí:
Na závěr si ukážeme, jak nakreslit výseč:
kontext.beginPath(); kontext.arc(100, 100, 80, 0, Math.PI); kontext.closePath(); kontext.stroke();
Takto jsme si nakreslili nevyplněný půlkruh. Poté vykreslíme plný
půlkruh a v metodě arc()
přidáme volitelný parametr
určující směr vykreslování:
kontext.beginPath(); kontext.arc(300, 100, 80, 0, Math.PI, true); kontext.closePath(); kontext.fill();
Kružnice se ve výchozím nastavení vykresluje ve směru hodinových
ručiček. Toto jsme změnili přidáním volitelného parametru
smer
. Pokud je hodnota parametru smer
nastavena na
true
, vykreslování se obrátí:
Dnes jsme si ukázali kreslení základních geometrických tvarů. Plátno nabízí mnohem více dalších možností, které si ukážeme příště.
V příští lekci, Stylování obrázků a vložení textu na plátno v JavaScriptu, budeme pokračovat v práci s obrázky, naučíme se změnit jejich barvu, šířku čáry nebo doplnit na canvas text.
Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 1752x (14.87 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript