Lekce 16 - 2D kontext plátna v JavaScriptu
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 podrobně podíváme na plátno. 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:
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.
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.
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:
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:
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í 0
– 1
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:
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é.
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:
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.

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:
Nyní byste již měli být schopni ovládat <canvas>
v JavaScriptu. Doporučuji si vyzkoušet cvičení, který má tento kurz k
dispozici.
V následujícím cvičení, Řešené úlohy k 15. a 16. lekci JavaScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.
Stáhnout
Staženo 321x (232.19 kB)
Aplikace je včetně zdrojových kódů v jazyce JavaScript
Komentáře


Zobrazeno 6 zpráv z 6.