Válí se ti projekty v šuplíku? Dostaň je mezi lidi a získej cool tričko a body na profi IT kurzy v soutěži ITnetwork summer 2017!
Přidej si svou IT školu do profilu a najdi spolužáky zde na síti :)

12. díl - Obrázky a kreslení na canvas v JavaScriptu

JavaScript Základní konstrukce Obrázky a kreslení na canvas v JavaScriptu

ONEbit hosting Unicorn College Tento obsah je dostupný zdarma v rámci projektu IT lidem. Vydávání, hosting a aktualizace umožňují jeho sponzoři.

Vítám vás u další lekce o tvorbě webových stránek a aplikací v JavaScriptu. V lekci minulé, Dokončení editoru tabulek v JavaScriptu, jsme dokončili editor tabulek. V tomto JavaScript tutoriálu se podíváme na zub obrázkům.

Na webu existují dva typy obrázků – statické a dynamické. Statické obrázky již znáte a moc se s nimi nedá kouzlit. Jsou to obyčejné obrázky (tag <img>), se kterými můžete provádět jen několik málo základních operací. Povětšinou s nimi manipulujeme jen jako s prvkem DOMu. Dynamické obrázky již mohou být v dokumentu HTML znázorněny 2 značkami – SVG a Canvas. Přičemž první jmenovaná sice není striktně statická, ale vesměs v JavaScriptu s ní toho moc nenaděláme (zatím). Canvas již je o trochu zajímavější a zároveň jediný, jehož obsah nelze definovat jinak než JavaScriptem. Projdeme si to postupně.

Statické obrázky

Jak jsem již zmínil v úvodu, jedná se o klasický obrázek, který v HTML definujeme tagem <img>. Můžeme mu samozřejmě obsluhovat různé události jako je kliknutí a to úplně stejným způsobem jako třeba na tlačítko. V JavaScriptu ho můžeme vytvořit buďto klasicky jako prvek DOM

var img = document.createElement("img");

Nebo můžeme vytvořit nový objekt Image, což je zkrácená varianta tvorby prvku DOM.

var img = new Image();

Načtení obrázku

Velkým problémem je načítání obrázku (ostatně jako načítání čehokoliv v JavaScriptu). 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 load, není žádný problém. Prohlížeč zajistí, že obsluha se zavolá až po načtení všeho (i obrázku).

V případě, že si obrázky zpracováváme až v JavaScriptu, musíme na načtení počkat. Poslouží nám k tomu událost load na daném obrázku.

var img = new Image();
img.src = "cesta/k/obrazku.jpg";

img.onload = function () {
        // tady víme, že je obrázek načtený
}

Příklad: Přepínač

Vytvoříme si přepínač. Jistě znáte přepínač ON-OFF. Obrázky si stáhněte níže a ideálně pojmenujte switch0.png a switch1.png.

Vytvořme stránku, kde bude obrázek s ID prepinac a jako výchozí cestu mu dáme k obrázku prepinac0.png.

<img src="switch0.png" id="prepinac" />

Vytvoříme si skript, kde deklarujeme proměnnou prepinac a po načtení stránky do ní dosadíme náš obrázek přepínače. Dále si vytvoříme funkci Prepni() a nastavíme ji jako obsluhu události pro kliknutí na obrázek.

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

Img.src × img.getAttribu­te("src")

Teď již je to jen o podmínce a změně src, ale... objekt obrázku (u OOP zjistíte, že se jmenuje HTMLImageElement) má vlastnost src. Nabízí se tedy možnosti změnit hodnotu jeho atributu nebo ji dosadit rovnou do této vlastnosti. Jenže... Tyto dvě možnosti se v některých prohlížečích chovají trochu odlišně. Zatímco metoda getAttribute() vrátí přesně tu hodnotu, co je v parametru, src vrátí absolutní cestu. Pokud tedy budeme porovnávat, tak až na pár výjimek budeme porovnávat s hodnotou v atributu. Na vyzkoušení si hodnoty změníme již přes vlastnost src.

function Prepni() {
        if (prepinac.getAttribute("src") == "switch0.png") {
                prepinac.src = "switch1.png"
        } else {
                prepinac.src = "switch0.png"
        }
}

Stránku si otevřete a vyzkoušejte, přepínač by měl fungovat. Všimněte si, že vůbec nemusíme ošetřovat, kdy se obrázek načte, protože nás to nezajímá. Uživatel bude čekat tak či tak, ale my jsme od toho odstínění, pokud s obrázkem dále nepracujeme.

Nyní se přesuneme k dynamickým obrázkům.

Dynamické obrázky

Dynamické obrázky se kreslí na plátno, což je tag <canvas>. Tento element MUSÍ mít atributy width a height. Pokud je neuvedeme nebo je nastavíme třeba v CSS, některé prohlížeče to nepochopí a plátno rozmažou. Na tento samotný element však ještě kreslit nemůžeme, musíme si získat jeho kontext. Možná si říkáte k čemu je to dobré, ten kontext? Ono je totiž rozdíl, když na plátno kreslíte 3D hru a 2D stromeček. 3D se v současnosti teprve prosazuje jako standard WebGL a tím se teď zabývat nebudeme, nás bude zajímat jen kontext 2D. Více jich v současnosti neexistuje.

Získání kontextu plátna

Kontext plátna získáme voláním metody getContext() a jako parametr ji předáme formou textového řetězce typ požadovaného kontextu. V našem případě 2d.

var context = canvas.getContext("2d");

Na tento kontext již můžeme volat různé metody pro vykreslení na plátno.

Čtverce a obdélníky

Základním objektem je obdélník. Máme předdefinované dvě základní metody, kterými můžeme obdélník nakreslit. Jsou jimi fillRect() a strokeRect(). Obě mají stejné argumenty a to x, y, výška a šířka. Funkce fillRect() odbélník vyplní, strokeRect() vykreslí pouze jeho obrys.

context.fillRect(50, 50, 100, 100)
context.strokeRect(200, 50, 100, 100);
Kreslení obdélníků na plátno v JavaScriptu

Čáry

Čáry se na plátno kreslí pomocí tzv. cest. Tyto cesty musíme (resp. měli bychom) je začít a uzavřít. Pro vytvoření cesty použijeme funkci beginPath(), pro uzavření pak closePath(). Samotnou čáru vykreslíme metodou lineTo(x, y). Pozice se odvíjí od poslední nastavené pozice kurzoru (zprvu 0;0), kterou nastavíme funkcí moveTo(x, y). Tato funkce nevykreslí nic, pouze přesune kurzor plátna na danou pozici. Cestu vykreslíme buďto metodou fill(), která vyplní celou cestu barvou (takto se dají kreslit vlastní tvary - proto je třeba cesty uzavírat), nebo funkcí stroke(), která vykreslí pouze čáry z dané cesty. Jednoduchý příklad vykreslí čáru z bodu 20;20 do 40;150.

context.beginPath();
context.moveTo(20, 20);
context.lineTo(40, 150);
context.closePath();
context.stroke();
Kreslení čar na canvas v JavaScriptu

Kruhy, kružnice a výseče

Další, co můžeme na plátno kreslit, jsou kruhy, kružnice a jejich výseče. To vše umí funkce context.arc(), jejíž syntaxe je následovná:

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

Argumenty x a y určují opět absolutní pozici. Radius udává poloměr kružnice, pocatecniUhel je úhel, od které se má kružnice resp. výseč vykreslit. Je udán v radiánech. Z matematiky všichni samozřejmě víme, že obvod kružnice je 2*PI a že stupně se převedou na radiány (PI/180)*stupně. Poslední proměnná je smer. Jedná se o logickou hodnotu (true/false), která udává, jestli se bude kružnice vykreslovat ve směru hodinových ručiček nebo proti němu. Základně je nastaveno true, tedy ve směru hodinových ručiček.

Kruh tedy nakreslíme takto:

context.arc(100, 100, 80, 0, Math.PI*2);

Odměnou za tak složitý skript nám bude takovýto kruh.

Kreslení kruhů na canvas v JavaScriptu

Styly

Někdy je třeba, aby kresba nějak vypadala. Na to jsou tu styly. Rozlišujeme styly pro vyplnění (fill) a vykreslení obrysu (stroke). Styly lze aplikovat na všechny objekty od obdélníků po kruhy. Máme k dispozici dvě základní proměnné, se kterými počítají metody stroke() a fill(). Jednak je to fillStyle a pak také strokeStyle. Jak již jsem říkal, jsou to proměnné a jejich hodnoty jsou zápisy barev. Můžeme použít klasický hexadecimální zápis z CSS např. #ffffff nebo rgb(255,255,255). Lze použít také rgba(255,255,­255,0.5), kde poslední hodnota je tzv. alfa kanál (průhlednost) nebo hsl a hsla (stejně jako v CSS 3). A poslední možností je pokud má barva svůj název, uvést ten (např. green).

Ukažme si jednoduché stylování objektů:

// Styly musí být vždy před samotným vykreslením (zavoláním metody fill, stroke nebo samovykreslovacích metod, jako jsou fillRect, strokeRect ...)

context.fillStyle = "#a8c101";
context.fillRect(10, 10, 50, 50);
Stylování canvasu v JavaScriptu

Externí obrázky

Můžeme na plátno samozřejmě vykreslovat i existující obrázky, musíte je však mít načtené, jinak se nevykreslí. Vykreslení obrázku docílíme jednoduše metodou drawImage(), které jako první parametr předáme obrázek a druhý a třetí jsou pozice X a Y kam se obrázek vykreslí. Existují ještě metody s parametry pro zvětšení/zmenšení a ořezání obrázků.

Vykreslení obrázku na canvas v JavaScriptu

Text

Kromě všelijakých tvarů můžeme na plátno vykreslit i text. To se dá využít třeba jako watermark na obrázcích ve vaší galerii, popisky ke grafům nebo úplně jinak, jak vám to jen vaše fantazie dovolí. Základní funkce je fillText(text, x, y). Text zde zastupuje textový řetězec, který chceme vypsat. X a Y jsou absolutní pozice. Jednoduchý text vykreslíme třeba takto:

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

Text bude ale bez stylů a celkem malý. Proto máme k dispozici proměnnou con­text.font, kterou musíme jako třeba fillStyle volat ještě před vykreslením textu. Hodnoty proměnné jsou totožné se zápisem v CSS u stejnojmenné vlastnosti font. Nastavíme velikost textu třeba na 30 pixelů a použijeme font sans-serif.

context.font = "30px sans-serif"
context.fillText("itnetwork.cz", 50, 50);
Vypsání textu na canvas v JavaScriptu

To by na úvod stačilo. V příští lekci, 2D kontext plátna v JavaScriptu, se podíváme na plátno ještě podrobněji.


 

Stáhnout

Staženo 331x (106.96 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript

 

 

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
Jak se ti líbí článek?
13 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.
Miniatura
Všechny články v sekci
Základní konstrukce jazyka JavaScript
Miniatura
Následující článek
2D kontext plátna v JavaScriptu
Aktivity (4)

 

 

Komentáře
Zobrazit starší komentáře (3)

Avatar
Filip (animátor/programator):4. května 15:51

Prečo mi nič okrem externého obrázku nefunguje nefunguje to ani keď som si stiahol zdroja nič nevikresli ani čiaru , štvorec alebo kruh proste nič len obrázok

Odpovědět 4. května 15:51
Nikdy sa nevzdávaj a choď si za svojim snom.......
Avatar
Odpovídá na Filip (animátor/programator)
Michal Žůrek (misaz):4. května 18:51

nevím, zkus dát F12 a podívat se jestli to nevypsalo nějaký error. Můžeš to zkusit i v jiném prohlížeči.

Odpovědět 4. května 18:51
Nesnáším {}, proto se jim vyhýbám.
Avatar
David Čápka
Tým ITnetwork
Avatar
Odpovídá na Filip (animátor/programator)
David Čápka:4. května 19:08

Mám dojem, že třeba Chrome tohle na localhostu nepodporuje, zkus to nahrát na web.

Odpovědět 4. května 19:08
Miluji svou práci a zdejší komunitu, baví mě se rozvíjet, děkuji každému členovi za to, že zde působí.
Avatar
Odpovídá na David Čápka
Michal Žůrek (misaz):4. května 20:29

kreslení na canvas podporuje, nepodporuje načítání obrázků. Samotné kreslení čar mu musí fungovat.

Odpovědět 4. května 20:29
Nesnáším {}, proto se jim vyhýbám.
Avatar
Odpovídá na David Čápka
Filip (animátor/programator):5. května 5:52

Mám to už na webe a aj tak to nejde.. :(

Editováno 5. května 5:53
Odpovědět 5. května 5:52
Nikdy sa nevzdávaj a choď si za svojim snom.......
Avatar
Filip (animátor/programator):5. května 5:58

A myslím že chyba môže byť aj vo vašom zdrojaku napr.: Tu chýba

<Body>
Odpovědět 5. května 5:58
Nikdy sa nevzdávaj a choď si za svojim snom.......
Avatar
Odpovídá na David Čápka
Filip (animátor/programator):5. května 7:36

Už som to opravil chyba bola aj v tom body aj v mojom zápise tetaz moj "paint" vizera takto viz. screenshoot:

Odpovědět 5. května 7:36
Nikdy sa nevzdávaj a choď si za svojim snom.......
Avatar
Jan Felkl
Člen
Avatar
Jan Felkl:6. července 17:24

Ahoj příklad přepínač funguje ale jakmile jsem obrázky dal do adresáře img tak to přestalo fungovat, cestu jsem změnil.
Něco dělám špatne ale co?

function Prepni() {
if (prepinac.getAt­tribute("src") == "img\prep0.png") {
prepinac.src = "img\prep1.png"
} else {
prepinac.src = "img\prep0.png"
}
}

 
Odpovědět 6. července 17:24
Avatar
Odpovídá na Jan Felkl
Michal Žůrek (misaz):6. července 17:27

V javascriptu se jako oddělovač složek nepoužívá \ ale /

Odpovědět 6. července 17:27
Nesnáším {}, proto se jim vyhýbám.
Avatar
Jan Felkl
Člen
Avatar
Jan Felkl:6. července 17:30

dik už to jede

 
Odpovědět 6. července 17:30
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 10 zpráv z 13. Zobrazit vše