Vánoční nadílka Vánoční nadílka
Vánoční akce! Daruj lepší budoucnost blízkým nebo sobě. Až +50 % zdarma na dárkové poukazy. Více informací

Lekce 13 - 2D kontext plátna v JavaScriptu

JavaScript Základní konstrukce 2D kontext plátna v JavaScriptu American English version English version

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 minulé lekci, Obrázky a kreslení na canvas v JavaScriptu, jsme se věnovali obrázkům a naučili se pracovat s canvasem. V dnešním JavaScript tutoriálu se na plátno podíváme podrobněji. Projdeme si postupně všechny jeho možnosti.

Mazání obdélníků

V minulém díle jsme lehce nakousli kreslení obdélníků. Uvedli jsme si metody fillRect() a strokeRect(). K obdélníkům se ještě váže metoda clearRect(), která vymaže obsah plátna na dané ploše. Parametry má stejné jako dvě výše zmíněné metody. Jaký je však rozdíl mezi clearRect() a fillRect(), když nastavíme výplň na bílou? Plátno totiž ve výchozím stavu není bílé, ale je průhledné. Pokud tedy vymažeme plátno pomocí fillRect(), sice uvidíme bílou plochu, ale neuvidíme pozadí plátna a to co bylo pod plátnem.

Obdélník v cestě

Poslední možností jak vykreslit obdélník je vložit ho do cesty. Ačkoliv by se to na první pohled mohlo zdát zbytečné, když máme metody fillRect() a strokeRect(), tak je to velmi výhodné, když chceme vybarvit obdélník a dát mu zároveň rámeček. Jednoduše obdélník vykreslíme jako cestu, vykreslíme obsah a rámeček.

kontext.beginPath();
kontext.rect(10, 10, 60, 60);
kontext.closePath();
kontext.fillStyle = "red";
kontext.strokeStyle = "blue";
kontext.stroke();
kontext.fill();

Výsledek:

Plátno
localhost

Transformace kontextu

Velmi důležité jsou při zpracovávání obrázku transformace. Čas od času se bude hodit, když pozice nula nebude nulou. Asi ten nejjednodušší případ je, když kolem canvasu budeme mít nějaký hodně specifický 10px široký rámeček, který bychom jen v CSS nenastylovali. Samozřejmě všude můžeme vypisovat, aby se vykreslovalo na x + 10, y + 10, ale jednoduší pro nás bude využít posunu kontextu. U rotací to bude o to zajímavější a mnohdy jediná cesta jak docílit daného výsledku.

Uložení kontextu

Před jakoukoliv manipulací s kontextem je dobré si ho uložit. My ho sice potom můžeme vrátit do pozice x -10 a y -10, ale je to zbytečně pracné a navíc si musíme pamatovat tyto hodnoty. Proto má kontext metody save() a restore(), ani jedna nepožaduje žádný parametr. Metoda save() si uloží aktuální transformace a metoda restore() je obnoví.

Jako příklad si vykreslíme obrázek s červeným rámečkem, ačkoliv je toto nejjednodušší řešit s pomocí CSS, zkusíme to v JavaScriptu.

Nejprve si načteme plátno, kontext a obrázek, to již zvládnete sami. Kontextu nastavíme barvu výplně např. na červenou a překreslíme jí celý <canvas>. Poté kontext uložíme.

kontext.fillStyle = "#f00";
kontext.fillRect(0, 0, 510, 340);

kontext.save();

Posun kontextu

Posun kontextu provádíme metodou translate(), která přijímá parametry x a y pro souřadnice posunu. Nový nulový bod bude na těchto souřadnicích. My si plátno posuneme o kladných 10px jak po ose x, tak po ose y.

kontext.translate(10, 10);

Nyní na pozici [0; 0] vykreslíme obrázek a kontext plátna obnovíme.

kontext.drawImage(obrazek, 0, 0);
kontext.restore();

Když si nyní aplikaci otevřeme, všimneme si, že ačkoliv jsme zadali, ať se obrázek nakreslí na [0;0], tak se vykreslil na [10;10]. Může za to právě náš posun.

Plátno
localhost

Nezapomeňte vrátit kontext, kdybyste s ním ještě někdy potřebovali pracovat.

Zvětšení/zmenšení

Kontext můžeme zmenšovat a zvětšovat. Slouží k tomu metoda scale(), která jako parametry přijímá násobky skutečné hodnoty pro souřadnice X a Y. Pro zmenšování se zadávají desetinná čísla menší než 1.

Plátno
localhost

Rotace

Poslední operací je rotace. Často potřebujeme něco otočit. Např. když potřebujeme udělat kosočtverec nebo kosodélník, není nic jednoduššího než otočit kontext. Samozřejmě bychom mohli body přepočítávat, ale bylo by to zbytečně komplikované. Kontext otáčíme metodou rotate(), která jako parametr přijímá úhel v radiánech.

kontext.save();
kontext.translate(100, 100);
kontext.rotate(45 * Math.PI / 180);
kontext.strokeRect(0, 0, 50, 50);
kontext.restore();

Výsledek:

Plátno
localhost

Stín

Všechny operace, které něco na canvas nakreslí, můžeme provádět se stínem. Vlastností shadowColor nastavíme barvu stínu. Vlastnostmi shadowOffsetX a shadowOffsetY nastavíme posun stínu a pomocí shadowBlur jak moc bude rozostřený.

kontext.shadowColor = "red";
kontext.shadowOffsetX = 6;
kontext.shadowOffsetY = 3;
kontext.shadowBlur = 10;

Výsledek:

Plátno
localhost

Barevné přechody

Občas se hodí obrázek "vylepšit" barevnými přechody. Existují 2 typy přechodů - lineární a kruhové (radiální). Oba se dají nastavit jak pro výplň, tak pro obrys.

Lineární přechod

Lineární přechod je jednoduchý, barvy se postupně mění jak řekneme a to za sebou. Vytváří se metodou createLinearGradient() na objektu kontextu a předáváme jí 4 parametry. Jsou to souřadnice x a y pro počátek a pro konec gradientu. Nově vzniklý objekt disponuje metodou addStopColor(), která přidá gradientu další barvu. Tato metoda přijímá jako první parametr pozici "zastavení" v rozmezí 01 a jako druhý danou barvu.

let gradient = kontext.createLinearGradient(0, 0, 100, 0);
gradient.addColorStop(0, "yellow");
gradient.addColorStop(0.2, "orange");
gradient.addColorStop(0.4, "pink");
gradient.addColorStop(0.6, "red");
gradient.addColorStop(0.8, "green");
gradient.addColorStop(1, "blue");

kontext.fillStyle = gradient;
kontext.fillRect(0, 0, 100, 100);

kontext.font = "19px Calibri"
kontext.fillText("ITnetwork.cz", 0, 115);

Výsledek:

Plátno
localhost

Radiální přechod

Radiální neboli kruhový přechod se používá úplně stejně, jen vytvoří jiný efekt. Metoda, která jej vytvoří, se nazývá createRadialGradient() a přijímá 6 parametrů. x a y pro počáteční bod, poloměr a to vše ještě jednou i pro koncový bod.

V hodnotách je poměrně zmatek. První pozice x a y je vlastně střed, první poloměr je poloměr, u kterého začne přechod. Pokud bude nula, přechod začne již od středu. Pokud cokoli jiného, bude od středu první barva a až na zadaném poloměru začne přecházet. Pokud chcete docílit pravidelného kruhu, tak 4. a 5. parametr bude kopírovat první a druhý. Šestý parametr poté udává na jakém poloměru se přechod zastaví, dále již bude jen poslední barva. Nastavování barev je stejné.

Plátno
localhost

Obrázková výplň

Jedna z dalších možností výplně (dostupná i pro obrys) je obrázková výplň. Docílíme jí tak, že vytvoříme pattern (vzor) a ten nastavíme výplni (nebo obrysu). Pattern vytvoříme metodou createPattern(), kde jako první parametr předáme obrázek a jako druhý způsob opakovaní. Pro opakování po ose X i Y můžeme ponechat prázdný String.

let vzor = kontext.createPattern(obrazek, "");
kontext.fillStyle = vzor;

Výsledek:

Plátno
localhost

Jako vzor můžeme použít i jiný element <canvas>.

Práce s pixely

Až doposud za nás nějaké pixely řešil JavaScript, ale občas se hodí, abychom i my mohli pracovat s jednotlivými pixely.

Obrázková data

2D kontext plátna poskytuje objekt ImageData. Získáme jej metodou getImageData(), které jako parametry předáme souřadnice levého horního rohu a velikost výřezu. Tento objekt bude mít pole data, ve kterém jsou všechny RGBA hodnoty pixelů v tomto výběru. Pixely jsou řazené postupně, řádek po řádku, zleva doprava.

Práce s pixely na canvasu v JavaScriptu

Vytvořme si aplikaci, která invertuje barvy obrázku. Načtěme si zas plátno, kontext a obrázek. Na plátno vykreslíme obrázek a z obrázku si získáme obrázková data.

kontext.drawImage(img, 0, 0);
let dataObrazku = kontext.getImageData(0, 0, platno.width, platno.height);

Nyní cyklem projdeme všechny barvy, každý pixel je v poli zastoupen 4×, respektive každá jeho složka (R, G, B, A) tam má hodnotu. Cyklus tedy nebude mít klasickou inkrementaci, ale iterační proměnnou zvýšíme o 4.

for (let i = 0; i < dataObrazku.data.length; i += 4) {
}

V cyklu poté hodnotám i (R), i + 1 (G), i + 2 (B) nastavíme novou barvu. V našem případě odečítáme hodnotu barvy od 255, což je maximální hodnota. Tím hodnoty otočíme a docílíme efektu negativu. Alfa kanál nebudeme měnit.

dataObrazku.data[i + 0] = 255 - dataObrazku.data[i + 0];
dataObrazku.data[i + 1] = 255 - dataObrazku.data[i + 1];
dataObrazku.data[i + 2] = 255 - dataObrazku.data[i + 2];

Nakonec vložíme upravená ImageData do obrázku metodou putImageData() na pozici [0;0].

kontext.putImageData(dataObrazku, 0, 0);

Výsledek:

Plátno
localhost

Nyní byste již měli být schopni ovládat <canvas> v JavaScriptu. Doporučuji vyzkoušet si cvičení. V příští lekci, Časovače a animace v JavaScriptu, se podíváme na časovače a animace.


 

Stáhnout

Staženo 232x (232.19 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?
9 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 (12)

 

 

Komentáře

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.

Zatím nikdo nevložil komentář - buď první!