13. díl - 2D kontext plátna v JavaScriptu

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

minulém tutoriálu o tvorbě webových aplikací v JavaScriptu jsme se věnovali obrázkům a naučili se pracovat s canvasem. V tomto dílu se na plátno podíváme podrobněji. Projdeme si postupně všechny jeho možnosti a zmíníme si, že vzniká nový standard tohoto plátna a co tento nový standard bude zahrnovat.

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.translate(30, 0);
kontext.beginPath();
kontext.rect(10, 10, 20, 20);
kontext.closePath();
kontext.fillStyle = "orange"
kontext.strokeStyle = "blue"
kontext.stroke();
kontext.fill();

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ý rámeček, který v CSS neuděláme. Samozřejmě pak všude můžeme vypisovat, aby se vykresloval 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.

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 si zajistěte sami. Kontextu nastavíme barvu výplně třeba na červenou a překreslíme tím celý canvas. Poté kontext uložíme.

kontext.fillStyle = "#f00";
kontext.fillRect(0, 0, 500, 330);

kontext.save();

Posun kontextu

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

kontext.translate(10, 10);

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

kontext.drawImage(img, 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.

Posun kontextu canvasu v JavaScriptu

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 parametr přijímá násobek skutečné hodnoty pro X a Y. Pro zmenšování se zadává desetinné číslo.

Škálování canvasu v JavaScriptu

Rotace

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

Rotace kontextu v JavaScriptu

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 ShodowOffsetX a Y nastavíme posun stínu a shodowBlur jak moc se rozmaže.

kontext.shadowColor = "red";
kontext.shadowOffsetX = 60;
kontext.shadowOffsetY = 30;
kontext.shadowBlur = 10;

Výsledek:

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 createLinearGra­dient() na objektu kontextu a při jeho vytváření musíme zadat 4 parametry a to hodnoty X, Y pro počátek gradientu a konec gradientu. Nově vzniklý objekt má metodu addStopColor(), která přidá zastavovací barvu. Tato metoda přijímá jako první parametr pozici "zastavení" v rozmezí 0 – 1 a jako druhý danou barvu.

var 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;

Výsledek:

Lineární přechod na canvasu v JavaScriptu

Radiální přechod

Radiální neboli kruhový přechod se používá úplně stejně, jen to vytvoří jiný efekt. Metoda, která jej vytvoří, se jmenuje createRadialGra­dient() a přijímá 6 parametrů. Počáteční bod X, Y, poloměr a to vše i pro koncový bod. V hodnotách je docela 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, začne se rozplývat 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 je poté na jakém poloměru se přechod zastaví, dále již bude jen poslední barva. Nastavování barev je stejné.

Radiální přechod na canvasu v JavaScriptu

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.

var pattern = kontext.createPattern(img, "");
kontext.fillStyle = pattern;

Výsledek:

Obrázková výplň na canvasu v JavaScriptu

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 pro jakoukoliv manipulaci obsahuje objekt ImageData. ImageData získáme metodou getImageData(), které jako parametry předáme počátek souřadnic a velikost jakou má vyřezat. 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);
var imgData = 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 (RGBA) tam má hodnotu. Cyklus tedy nebude mít klasickou inkrementaci, ale iterační proměnnou zvýšíme o 4.

for (var i = 0; i < imgData.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.

imgData.data[i + 0] = 255 - imgData.data[i + 0];
imgData.data[i + 1] = 255 - imgData.data[i + 1];
imgData.data[i + 2] = 255 - imgData.data[i + 2];
Nakonec vložíme upravená ImageData do obrázku metodou putImageData na pozici 0, 0.
kontext.putImageData(imgData, 0, 0);

Výsledek:

Efekt negativu v JavaScriptu

Co se tu objeví někdy v budoucnosti?

Momentálně jsme téměř vyčerpali možnosti canvasu, tedy toho dnešního. V současnosti již vzniká standard jeho nové verze. Tento standart je ve velmi rané fázi a někdy v budoucnu doplní canvas o nové prvky. Těšit se můžete na:

  • Nové možnosti písma
  • Nové styly
  • Lepší práci s cestami
  • Elipsu
  • Zdokonalené vyřezávání
  • Podpora obrázkových bitmap (nového objektu)

Tyto novinky do článku nezahrnujeme z několika důvodů. V současnosti to až na nějaký experiment žádný prohlížeč nepodporuje a vše je ve stavu, ve kterém se to může ze dne na den úplně změnit. Mohou tam něco přidat, odebrat, přejmenovat, předělat,...

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


 

Stáhnout

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

 

  Aktivity (1)

Článek pro vás napsal Michal Žůrek (misaz)
Avatar
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.

Jak se ti líbí článek?
Celkem (7 hlasů) :
4.857144.857144.857144.857144.85714


 



 

 

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