Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
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í.

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:

Základní konstrukce jazyka JavaScript Základní konstrukce jazyka JavaScript

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:

Tvoje stránka
localhost

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:

Plátno
localhost

Čá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:

Plátno
localhost

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í:

Plátno
localhost

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:

Plátno
localhost

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 1497x (14.87 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

Předchozí článek
Práce s čísly a knihovna Math v JavaScriptu
Všechny články v sekci
Základní konstrukce jazyka JavaScript
Přeskočit článek
(nedoporučujeme)
Stylování obrázků a vložení textu na plátno v JavaScriptu
Článek pro vás napsal Michal Žůrek - misaz
Avatar
Uživatelské hodnocení:
670 hlasů
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