Lekce 24 - 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
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 se
náš kód zavolá, až bude načtena celá stránka.
V případě, že si obrázky vytváříme až v JavaScriptu, musíme na
načtení počkat. Použijeme tedy událost onload
na daném
obrázku:
let obrazek = new Image(); obrazek.src = "cesta/k/obrazku.jpg"; obrazek.onload = function () { // Zde víme, že je obrázek načtený }
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); // Další akce };
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() { // Zde víme, že je obrázek načtený }); obrazek.addEventListener('error', function() { console.error("Chyba při načítání obrázku: " + obrazek.src); // Další akce });
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:
Nyní vytvořme stránku, kde bude v <body>
obrázek
s id
prepinac
. Jako výchozí obrázek
nastavíme prepinac0.png
:
<img src="prepinac0.png" id="prepinac" alt="Přepínač" />
Doplníme skript, v němž deklarujeme proměnnou prepinac
a po
načtení stránky do ní dosadíme náš element obrázku přepínače.
Obrázku nastavíme obsluhu události kliknutí, v níž zavoláme funkci
prepni()
, kterou vzápětí doplníme.
let prepinac; window.onload = function() { prepinac = document.getElementById("prepinac"); prepinac.onclick = prepni; }
Změna atributu src
Ve funkci prepni()
budeme potřebovat zjistit a změnit
aktuální hodnotu atributu src
elementu <img>
.
Tento atribut získáme pomocí metody getAttribute()
, která
vrací přesnou hodnotu zapsanou v atributu. V podmínce ji pak
porovnáme s názvem jednoho z obrázků a poté nastavíme opačný
obrázek:
function prepni() { if (prepinac.getAttribute("src") == "prepinac0.png") { prepinac.src = "prepinac1.png"; } else { prepinac.src = "prepinac0.png"; } }
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 nežádoucím
výsledkům. Zatímco CSS mění velikost zobrazení plátna, nepřizpůsobuje
jeho vnitřní rozlišení, což může vést k rozmazanému nebo zkreslenému
obsahu v některých prohlížečích.
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()
. Jako
parametr jí předáme formou textového řetězce typ požadovaného
kontextu. V našem případě je to 2d
:
let platno; let kontext; window.onload = function () { platno = document.getElementById("platno"); kontext = platno.getContext("2d"); // Zde bude kód pro vykreslení jednotlivých geometrických tvarů }
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()
. Obě přijímají
stejné argumenty. V prvních dvou zadáme souřadnice levého horního rohu
obdélníku (x
a y
). Pomocí dalších dvou argumentu
nastavujeme výšku a šířku (width
a height
)
obdélníku. Metoda fillRect()
obdélník vyplní, metoda
strokeRect()
vykreslí pouze jeho obrys.
Kód výše doplníme a nakreslíme dva stejně velké čtverce:
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); }
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
.
Výsledek:
Čá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()
.
Samotnou čáru vykreslíme metodou lineTo()
. Čára se ve
výchozím nastavení pozice kurzoru vykreslí z pozice [0;0]
. Tuto
pozici můžeme změnit metodou moveTo()
. Metoda nevykreslí nic,
pouze přesune kurzor plátna na danou pozici. Obě uvedené metody přijímají
parametr x
a y
. Samotnou čáru pak vykreslíme
metodou stroke()
.
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ů.
Jednoduchý příklad níže vykreslí čáru z bodu [20;20]
do
[40;150]
:
kontext.beginPath(); kontext.moveTo(20, 20); kontext.lineTo(40, 150); kontext.closePath(); kontext.stroke();
Přidáním druhé čáry pak vytvoříme obrázek trojúhelníku. Je to proto, že při zavření cesty dochází k propojení výchozího bodu s konečným bodem:
kontext.beginPath(); kontext.moveTo(120, 20); kontext.lineTo(140, 150); kontext.lineTo(200, 100); kontext.closePath(); kontext.stroke();
Nyní můžeme použít také metodu fill()
, která vyplní
vnitřek cesty barvou a vykreslí vyplněný trojúhelník:
kontext.beginPath(); kontext.moveTo(270, 20); kontext.lineTo(290, 150); kontext.lineTo(350, 100); kontext.closePath(); kontext.fill();
Výsledek:
Kruhy, kružnice a výseče
Další metodou pro kreslení na plátno kreslit 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);
Parametry x
a y
určují pozici
středu kruhu, dále uvádíme jeho polomer
.
Následují parametry pocatecniUhel
a konecnyUhel
, zde
volíme, zda vykreslit celou kružnici nebo její výseč.
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ě
.
Kružnice se ve výchozím nastavení vykresluje ve směru hodinových
ručiček. Toto nastavení změníme doplněním volitelného parametru
smer
s hodnotu true
. Metodu arc()
musíme
používat uvnitř cesty.
Kruh tedy nakreslíme takto:
kontext.beginPath(); kontext.arc(100, 100, 80, 0, Math.PI * 2); kontext.closePath(); kontext.fill();
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 ukažme, jak nakreslit výseč. Takto si nakreslíme nevyplněný půlkruh:
kontext.beginPath(); kontext.arc(100, 100, 80, 0, Math.PI); kontext.closePath(); kontext.stroke();
Poté vykreslíme plný půlkruh a v metodě arc()
přidáním
volitelného parametru určíme směr vykreslování proti směru hodinových
ručiček:
kontext.beginPath(); kontext.arc(300, 100, 80, 0, Math.PI, true); kontext.closePath(); kontext.fill();
Výsledek:
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 1509x (14.87 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript