IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

14. diel - Obrázky a kreslenie na canvas v JavaScripte

V minulej lekcii, Cykly v JavaScripte druhýkrát , sme sa naučili používať kľúčové slová break, continue, návestí a cyklus do-while.

Vítam vás u ďalšej lekcie o tvorbe webových aplikácií v JavaScripte. V minulej lekcii, Cykly v JavaScripte druhýkrát , sme si prehĺbili naše znalosti o dátových typoch a ukázali si ďalšie konštrukcie pre tvorbu podmienok. V tomto JavaScript tutoriálu sa pozrieme na zub obrázkom, čím začneme ďalšie väčšie kapitolu - práca s grafikou v JavaScriptu.

Na webe existujú dva typy obrázkov - statické a dynamické. Statické obrázky už poznáte a moc sa s nimi nedá kúzliť. Sú to obyčajné obrázky (tag <img>), s ktorými môžete vykonávať len niekoľko málo základných operácií. Poväčšine s nimi manipulujeme len ako s prvkom domu. Dynamické obrázky už môžu byť v dokumente HTML znázornené 2 značkami - <svg> a <canvas>. Pričom prvý menovaná síce nie je striktne statická, ale napospol v JavaScripte s ňou toho veľa neurobíme (zatiaľ). Tag <canvas> už je o trochu zaujímavejšie a zároveň jediný, ktorého obsah nie je možné definovať inak ako JavaScriptom. Prejdime si všetko postupne.

Statické obrázky

Ako som už spomenul v úvode, jedná sa o klasický obrázok, ktorý v HTML definujeme tagom <img>. Môžeme mu samozrejme obsluhovať rôzne udalosti ako je kliknutie a to úplne rovnakým spôsobom ako napr. Pri tlačidle. V JavaScriptu ho môžeme vytvoriť buď klasicky ako prvok DOM:

let obrazek = document.createElement("img");

Alebo môžeme vytvoriť nový objekt Image, čo je skrátená varianta tvorby prvku DOM:

let obrazek = new Image();

Načítaní obrázka

Veľkým problémom je načítanie obrázku (ostatne ako načítanie čohokoľvek v JavaScriptu). 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č zabezpečí, že obsluha sa zavolá až po načítaní všetkého (i obrázka).

V prípade, že si obrázky vytvárame až v JavaScripte, musíme na načítanie počkať. Poslúži nám k tomu udalosť onload na danom obrázku.

let obrazek = new Image();
obrazek.src = "cesta / k / obrazku.jpg";

obrazek.onload = function () {
    // Tu vieme, že je obrázok načítaný
}

Príklad: Prepínač

Vytvoríme si prepínač. Iste poznáte prepínač ON-OFF. Obrázky si stiahnite nižšie a ideálne pomenujte prepinac0.png a prepinac1.png.

Základné konštrukcie jazyka JavaScript Základné konštrukcie jazyka JavaScript

Vytvorme stránku, kde bude obrázok s id #prepinac a ako predvolené cestu mu dáme k obrázku prepinac0.png.

<img src="prepinac0.png" id="prepinac" alt="Prepínač" />

Vytvoríme si skript, kde deklarujeme premennú prepinac a po načítaní stránky do nej dosadíme náš element obrázka prepínača. Ďalej si vytvoríme funkciu prepni() a nastavíme ju ako obsluhu udalosti pre kliknutia na obrázok.

let prepinac;

function prepni() {
}

window.onload = function() {
    prepinac = document.getElementById("prepinac");
    prepinac.onclick = prepni;
}

Img.src vs. img.getAttribute ( "src")

Teraz už je to len o podmienke a zmene src, ale ... Objekt obrázku (u OOP zistíte, že sa volá HTMLImageElement) má vlastnosť src. Ponúka sa teda možnosť zmeniť buď hodnotu HTML atribút src elementu <img> alebo ju dosadiť rovno do vlastnosti src, ktorú element v JavaScripte má. Lenže ... Tieto dve možnosti sa v niektorých prehliadačoch správajú trochu odlišne. Kým metóda getAttribute() vráti presne tú hodnotu, čo je v atribúte, vlastnosť src vráti absolútnu cestu. Ak teda budeme porovnávať, tak až na pár výnimiek budeme porovnávať s hodnotou v atribútu. Na vyskúšanie si zdroj obrázku zmeníme cez vlastnosť src.

function prepni() {
    if (prepinac.getAttribute("src") == "prepinac0.png") {
        prepinac.src = "prepinac1.png";
    } else {
        prepinac.src = "prepinac0.png";
    }
}

Stránku si otvoríte a vyskúšajte, prepínač by mal fungovať.

Tvoja stránka
localhost

Všimnite si, že vôbec nemusíme ošetrovať, kedy sa obrázok načíta, pretože nás to nezaujíma. Užívateľ bude čakať tak či tak, ale my sme od toho odtienenie, pokiaľ s obrázkom ďalej nepracujeme.

Teraz sa presunieme k dynamickým obrázkom.

Dynamické obrázky

Dynamické obrázky sa kreslí na plátno, ktoré je reprezentované elementom <canvas>. Tento element musí mať nastavené atribúty width a height. Ak je neuvedieme alebo je nastavíme napr. V CSS, niektoré prehliadače to nepochopia a plátno rozmažú. Na samotný element <canvas> však ešte kresliť nemôžeme, musíme si získať jeho kontext. Možno si hovoríte na čo je to dobré, získavať ešte kontext? Ono je totiž rozdiel, keď na plátno kreslíme 3D hru a 2D stromček. 3D sa v súčasnosti ešte len presadzuje ako štandard WebGL a tým sa teraz zaoberať nebudeme, nás bude zaujímať len kontext 2D.

Získanie kontextu plátna

Kontext plátna získame volaním metódy getContext() a ako parameter ju odovzdáme formou textového reťazca typ požadovaného kontextu. V našom prípade je to "2d".

let platno = document.getElementById("platno");
let kontext = platno.getContext("2d");

Na tomto kontexte už môžeme volať rôzne metódy pre vykreslenie na plátno.

Obdĺžniky

Základným objektom je obdĺžnik. Máme preddefinované dve základné metódy, ktorými môžeme obdĺžnik nakresliť. Sú nimi fillRect() a strokeRect(). Obe majú rovnaké argumenty a to x, y, výška a šírka. Funkcia fillRect() obdĺžnik vyplní, strokeRect() vykreslí len jeho obrys.

Html časť

<canvas width="320" height="200" id="platno"></canvas>

JS časť

let platno = document.getElementById("platno");
let kontext = platno.getContext("2d");
kontext.fillRect(50, 50, 100, 100);
kontext.strokeRect(200, 50, 100, 100);

výsledok:

Plátno
localhost

Čiary

Čiary sa na plátno kreslí pomocou tzv. Ciest. Tieto cesty musíme (resp. Mali by sme) je začať a uzavrieť. Pre začatie cesty použijeme metódu beginPath(), pre uzatvorenie potom closePath(). Samotnú čiaru vykreslíme metódou lineTo(x, y). Čiara sa nakreslí od poslednej nastavenej polohy kurzora (tá je na začiatku [0; 0]). Túto pozíciu môžeme nastaviť metódou moveTo(x, y). Metóda nevykreslí nič, len presunie kurzor plátna na danú pozíciu. Cestu vykreslíme buď metódou fill(), ktorá vyplní vnútro cesty farbou (takto sa dajú kresliť vlastné tvary, preto je treba cesty uzatvárať), alebo metódou stroke(), ktorá vykreslí len obrys danej cesty. Jednoduchý príklad nižšie vykreslí čiaru z bodu [20; 20] do [40; 150].

kontext.beginPath();
kontext.moveTo(20, 20);
kontext.lineTo(40, 150);
kontext.closePath();
kontext.stroke();

výsledok:

Plátno
localhost

Kruhy, kružnice a výseky

Ďalšie, čo môžeme na plátno kresliť, sú kruhy, kružnice a ich výseče. To všetko vie metóda arc(), ktorej syntax je nasledujúca:

context.arc(x, y, polomer, pocatecniUhel, konecnyUhel, smer);

Argumenty x a y určujú opäť absolútnu pozíciu, tu stredu. Argument polomer udáva polomer kružnice, pocatecniUhel je uhol, od ktorého sa má kružnice resp. výseč vykresliť. Je udaný v radiánoch. Z matematiky by sme si mali pamätať, že plný uhol 2 * PI a že stupňa sa prevedú na radiány ako (PI / 180) * stupně. Posledný argument je smer. Ide o logickú hodnotu (true / false), ktorá udáva, či sa bude kružnice vykresľovať v smere hodinových ručičiek alebo proti nemu. Základni je nastavený na true, teda v smere hodinových ručičiek. Metódu musíme používať vnútri cesty.

Kruh teda nakreslíme takto:

kontext.beginPath();
kontext.arc(100, 100, 80, 0, Math.PI * 2);
kontext.fill();

Odmenou za kód vyššie nám bude takýto kruh.

Výsledok v prehliadači:

Plátno
localhost

Štýly

Aby naše kresby dobre vyzerali, naučíme sa používať štýly. Rozlišujeme štýly pre vyplnenie (fill) a vykreslenie obrysu (stroke). Štýly možno aplikovať na všetky objekty od obdĺžnikov po kruhy. Máme k dispozícii dve základné vlastnosti, s ktorými ďalej pracujú metódy stroke() a fill(). Jednak je to fillStyle a potom tiež strokeStyle. Hodnoty týchto vlastností sú zápisy farieb. Môžeme použiť klasický hexadecimálne zápisnica z CSS, napr. #ffffff alebo rgb(255, 255, 255). Možno použiť aj rgba(255, 255, 255, 0.5), kde posledná hodnota je tzv. Alfa kanál (priehľadnosť), alebo hsl a hsla (rovnako ako v CSS 3). A poslednou možnosťou je uviesť názov, ak ho farba má (napr. "green").

Ukážme si jednoduché štýlovanie objektov:

// Štýly musí byť vždy pred samotným vykreslením (zavolaním metódy `fill()`, `stroke()` alebo samovykreslovacích metód, ako sú `fillRect()`, `strokeRect()`...)

kontext.fillStyle = "#a8c101";
kontext.fillRect(10, 10, 50, 50);

výsledok:

Plátno
localhost

Externé obrázky

Na plátno samozrejme môžeme vykresľovať aj existujúce obrázky, napr. Zo súborov. Musíme ich však mať načítané, inak sa nevykreslí. Vykreslenie obrázku docielime jednoducho metódou drawImage(), ktoré ako prvý parameter odovzdáme obrázok a ako druhý a tretí parameter pozície X a Y kam sa obrázok vykreslí. Existujú ešte metódy s parametrami pre zväčšenie / zmenšenie a orezanie obrázkov.

obrázok:

Vykreslenie obrázka na canvas v JavaScripte - Základné konštrukcie jazyka JavaScript

výsledok:

Plátno
localhost

Text

Okrem všakovakých tvarov môžeme na plátno vykresliť i text. To sa dá využiť napríklad ako watermark na obrázkoch vo vašej galérii, menovkami ku grafom alebo úplne inak, ako vám to len vaša fantázia dovolí. Základné funkcie je fillText(text, x, y). Text tu zastupuje textový reťazec, ktorý chceme vypísať. Argumenty x a y sú absolútnou pozície. Jednoduchý text vykreslíme napríklad takto:

kontext.fillText("itnetwork.cz", 50, 50);

Text ale bude bez štýlov a celkom malý. Preto máme k dispozícii vlastnosť context.font, ktorú musíme ako trebárs fillStyle nastaviť ešte pred vykreslením textu. Hodnoty premenné sú totožné so zápisom v CSS pri rovnomennej vlastnosti font. Nastavme veľkosť textu napr. Na 30 pixelov a použime font sans-serif.

kontext.font = "30px sans-serif";
kontext.fillText("ITnetwork.cz", 50, 50);

výsledok:

Plátno
localhost

To by na úvod do canvasu stačilo. V budúcej lekcii, 2D kontext plátna v JavaScripte , sa pozrieme na plátno ešte podrobnejšie.


 

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é 1503x (14.87 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript

 

Predchádzajúci článok
Cykly v JavaScripte druhýkrát
Všetky články v sekcii
Základné konštrukcie jazyka JavaScript
Preskočiť článok
(neodporúčame)
2D kontext plátna v JavaScripte
Článok pre vás napísal Michal Žůrek - misaz
Avatar
Užívateľské hodnotenie:
3 hlasov
Autor se věnuje tvorbě aplikací pro počítače, mobilní telefony, mikroprocesory a tvorbě webových stránek a webových aplikací. Nejraději programuje ve Visual Basicu a TypeScript. Ovládá HTML, CSS, JavaScript, TypeScript, C# a Visual Basic.
Aktivity