25. diel - Obrázky a kreslenie na canvas v JavaScripte
V minulej lekcii, Práca s číslami a knižnica Math v JavaScripte, sme si predstavili si knižnicu
Math
pre prácu s číslami.
V dnešnom tutoriáli sa začneme venovať ďalšej
väčšej kapitole, práci s grafikou v
JavaScripte. Ukážeme si, ako je možné z kódu
vkladať do stránky obrázky reprezentované tagom
<img>
a predstavíme si tag <canvas>
(v
preklade plátno). Na plátno sa potom naučíme nakresliť
jednoduché geometrické tvary.
Práca s obrázkami
Klasický obrázok v HTML definujeme tagom
<img>
. Môžeme mu samozrejme nastaviť obsluhu
udalostí, ako je kliknutie, a to úplne rovnakým spôsobom ako
napríklad pri tlačidle.
V JavaScripte obrázok vytvoríme ako akýkoľvek iný element DOM zápisom:
let image = document.createElement("img");
Rovnaký výsledok dosiahneme aj zápisom:
let image = new Image();
Tento variant zároveň umožňuje nastaviť obrázku rozmery. Požadovanú šírku a výšku obrázku v pixeloch zadáme ako parametre v zátvorke:
let image = new Image(100, 200); // 100 is the width and 200 is the height
Načítanie obrázku
Než s obrázkom začneme pracovať, musí sa načítať. Ak
máme obrázok v HTML a JavaScript spúšťame v obsluhe udalosti
onload
, nie je žiadny problém. Prehliadač zaistí, že sa náš
kód zavolá, až bude načítaná celá stránka.
V prípade, že si obrázky vytvárame až v JavaScripte, musíme na
načítanie počkať. Použijeme teda udalosť onload
na danom
obrázku:
let image = new Image(); image.src = "path/to/image.jpg"; image.onload = function () { // Here we know that the image is loaded }
Ďalšou dôležitou udalosťou pri práci s obrázkami je udalosť
onerror
, ktorá je aktivovaná, keď dôjde k chybe pri
načítaní obrázku. Ku kódu vyššie doplníme:
image.onerror = function() { console.error("Error while loading image: " + image.src); // Additional code };
V tomto príklade sa v prípade chyby pri načítaní obrázka zobrazí v konzole uvedený text. Obsluhu chyby je však možné upraviť aj rozšíriť o ďalšie akcie, ako je nastavenie náhradného obrázku alebo výpis informácie o chybe na stránke.
Ukážme si rovnaký kód s obsluhou udalostí pomocou metódy
addEventListener()
:
let image = new Image(); image.src = "path/to/image.jpg"; image.addEventListener('load', function() { // Here we know that the image is loaded }); image.addEventListener('error', function() { console.error("Error while loading image: " + image.src); // Additional code });
Všimnime si, že sme udalosť načítania nenastavili ako
DOMContentLoaded
, ale ako load
. Takto overíme, že
boli načítané aj externé zdroje (ako napríklad obrázky) a
nie iba štruktúra HTML stránky, teda všetky tagy DOM
elementov.
Prepínanie obrázkov
Poďme si ukázať jednoduchý príklad, v ktorom budeme meniť obrázok na
stránke. Vytvoríme si prepínač. Po kliknutí na obrázok so zapnutým
prepínačom vložíme do stránky obrázok s vypnutým prepínačom a naopak.
Obrázky sú na stiahnutie nižšie, pomenujeme ich shunt0.png
a
shunt1.png
a uložíme ich do zložky nového projektu:
Teraz vytvorme stránku, kde bude v <body>
obrázok s
id
shunt
. Ako východiskový obrázok nastavíme
shunt0.png
:
<img src="shunt0.png" id="shunt" alt="Shunt" />
Doplníme skript, v ktorom deklarujeme premennú shunt
a po
načítaní stránky do nej dosadíme náš element obrázku prepínača.
Obrázku nastavíme obsluhu udalosti kliknutia, v ktorej zavoláme funkciu
switchIt()
, ktorú vzápätí doplníme.
let shunt; window.onload = function() { shunt = document.getElementById("shunt"); shunt.onclick = switchIt; }
Zmena atribútu src
Vo funkcii switchIt()
budeme potrebovať zistiť a zmeniť
aktuálnu hodnotu atribútu src
elementu <img>
.
Tento atribút získame pomocou metódy getAttribute()
, ktorá
vracia presnú hodnotu zapísanú v atribúte. V podmienke ju
potom porovnáme s názvom jedného z obrázkov a potom nastavíme opačný
obrázok:
function switchIt() { if (shunt.getAttribute("src") == "shunt0.png") { shunt.src = "shunt1.png"; } else { shunt.src = "shunt0.png"; } }
Keby sme v prvej časti podmienky namiesto metódy
getAttribute("src")
použili vlastnosť src
a
zapísali shunt.src
, získame absolútnu cestu k súboru s
obrázkom, napríklad
https://www.example.com/images/my-image.jpg
.
Stránku si otvoríme a prepínač vyskúšame:
Plátno
Teraz si predstavíme plátno a ukážeme si, ako naň kresliť. Plátno je vhodné použiť pre prípady, keď potrebujeme vytvárať obrázky dynamicky, pretože jeho obsah musíme definovať programovo v JavaScripte.
Plátno je reprezentované párovým tagom <canvas>
. Tento
element musí mať nastavené atribúty width
a
height
priamo v tagu <canvas>
. Ak ich nezadáme
alebo ich definujeme iba v CSS, môže to viesť k nežiaducim výsledkom.
Zatiaľ čo CSS mení veľkosť zobrazenia plátna, neprispôsobuje jeho
vnútorné rozlíšenie, čo môže viesť k rozmazanému alebo skreslenému
obsahu v niektorých prehliadačoch.
Do tela novej HTML stránky teda vložíme plátno takto:
<canvas width="500" height="500" id="canvas"></canvas>
Získanie kontextu plátna
Aby sme mohli na plátno začať kresliť, musíme si získať jeho kontext. Kontext určuje, aký typ obsahu budeme vytvárať. Existujú rôzne typy kontextov, my sa zameriame na 2D kontext, ktorý je ideálny pre väčšinu grafických úloh.
Pre prácu s 3D grafikou poskytuje JavaScript knižnicu WebGL (Web Graphics Library). My si ju však v tomto kurze základov predstavovať nebudeme a zameriame sa iba na prácu s 2D kontextom.
Kontext plátna získame volaním metódy getContext()
. Ako
parameter jej odovzdáme formou textového reťazca typ požadovaného
kontextu. V našom prípade je to 2d
:
let canvas; let context; window.onload = function () { canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); // Here will be the code for rendering individual geometric shapes }
Na tomto kontexte už môžeme volať rôzne metódy na kreslenie.
Obdĺžniky
Základným objektom je obdĺžnik. Obdĺžnik nakreslíme pomocou metódy
fillRect()
alebo strokeRect()
. Obe prijímajú
rovnaké argumenty. V prvých dvoch zadáme súradnice ľavého horného rohu
obdĺžnika (x
a y
). Pomocou ďalších dvoch
argumentov nastavujeme výšku a šírku (width
a
height
) obdĺžnika. Metóda fillRect()
obdĺžnik
vyplní, metóda strokeRect()
vykreslí iba jeho obrys.
Kód vyššie doplníme a nakreslíme dva rovnako veľké štvorce:
let canvas; let context; window.onload = function () { canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); context.fillRect(50, 50, 100, 100); context.strokeRect(200, 50, 100, 100); }
Plnému štvorcu sme nastavili súradnice x
a y
na
hodnotu 50
, výšku a šírku sme nastavili na 100
.
Obrys štvorca má rovnaké hodnoty, iba os x
je posunutá na
pozíciu 200
.
Výsledok:
Čiary a trojuholníky
Čiary sa na plátno kreslia pomocou tzv. ciest. Tieto cesty musíme začať
a uzavrieť. Najprv teda voláme metódu beginPath()
, ktorá
vytvorí novú cestu a prerušuje predchádzajúcu, pokiaľ kreslíme viac
nezávislých obrazcov. Na uzavretie cesty zavoláme metódu
closePath()
.
Samotnú čiaru vykreslíme metódou lineTo()
. Čiara sa v
predvolenom nastavení pozície kurzora vykreslí z pozície [0;0]
.
Túto pozíciu môžeme zmeniť metódou moveTo()
. Metóda
nevykreslí nič, iba presunie kurzor plátna na danú pozíciu. Obe uvedené
metódy prijímajú parameter x
a y
. Samotnú čiaru
potom vykreslíme metódou stroke()
.
Aj v ďalších príkladoch musíme najskôr počkať na načítanie dokumentu, potom získať element plátna z HTML súboru a nastaviť mu kontext. V ukážkach však už budeme uvádzať iba kód na kresbu jednotlivých geometrických tvarov.
Jednoduchý príklad nižšie vykreslí čiaru z bodu [20;20]
do
[40;150]
:
context.beginPath(); context.moveTo(20, 20); context.lineTo(40, 150); context.closePath(); context.stroke();
Pridaním druhej čiary potom vytvoríme obrázok trojuholníka. Je to preto, že pri zatvorení cesty dochádza k prepojeniu východiskového bodu s konečným bodom:
context.beginPath(); context.moveTo(120, 20); context.lineTo(140, 150); context.lineTo(200, 100); context.closePath(); context.stroke();
Teraz môžeme použiť aj metódu fill()
, ktorá vyplní
vnútro cesty farbou a vykreslí vyplnený trojuholník:
context.beginPath(); context.moveTo(270, 20); context.lineTo(290, 150); context.lineTo(350, 100); context.closePath(); context.fill();
Výsledok:
Kruhy, kružnice a výseče
Ďalšou metódou na kreslenie na plátno kresliť je metóda
arc()
. Tá vie nakresliť kruh, kružnicu a ich výseče. Jej
syntax je nasledovná:
context.arc(x, y, radius, initialAngle, finalAngle, direction);
Parametre x
a y
určujú pozíciu
stredu kruhu, ďalej uvádzame jeho radius
(polomer). Nasledujú parametre initialAngle
a
finalAngle
, tu volíme, či vykresliť celú kružnicu alebo jej
výseč.
Každý uhol udávame v radiánoch. Plný uhol
je 2 * PI
, stupne sa prevedú na radiány ako
(PI / 180) * stupně
.
Kružnica sa v predvolenom nastavení vykresľuje v smere hodinových
ručičiek. Toto nastavenie zmeníme doplnením voliteľného parametra
direction
s hodnotu true
. Metódu arc()
musíme používať vo vnútri cesty.
Kruh teda nakreslíme takto:
context.beginPath(); context.arc(100, 100, 80, 0, Math.PI * 2); context.closePath(); context.fill();
Pridajme si k existujúcemu príkladu ešte ukážku na vykreslenie kružnice:
context.beginPath(); context.arc(300, 100, 80, 0, Math.PI * 2); context.closePath(); context.stroke();
V prehliadači sa zobrazí:
Na záver si ukážme, ako nakresliť výseč. Takto si nakreslíme nevyplnený polkruh:
context.beginPath(); context.arc(100, 100, 80, 0, Math.PI); context.closePath(); context.stroke();
Potom vykreslíme plný polkruh a v metóde arc()
pridaním
voliteľného parametra určíme smer vykresľovania proti smeru hodinových
ručičiek:
context.beginPath(); context.arc(300, 100, 80, 0, Math.PI, true); context.closePath(); context.fill();
Výsledok:
Dnes sme si ukázali kreslenie základných geometrických tvarov. Plátno ponúka oveľa viac ďalších možností, ktoré si ukážeme nabudúce.
V budúcej lekcii, Štylovanie obrázkov a vloženie textu na plátno v JavaScripte, budeme pokračovať v práci s obrázkami, naučíme sa zmeniť ich farbu, šírku čiary alebo doplniť na canvas text.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 4x (15 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript