15. diel - 2D kontext plátna v JavaScripte
V minulej lekcii, Obrázky a kreslenie na canvas v JavaScripte , sme sa venovali obrázkom a naučili sa pracovať s canvas. V dnešnom JavaScript tutoriálu sa na plátno pozrieme podrobnejšie. Prejdeme si postupne všetky jeho možnosti.
Mazanie obdĺžnikov
V minulom diele sme zľahka načali kreslenie obdĺžnikov. Uviedli sme si
metódy fillRect()
a strokeRect()
. K obdélníkům sa
ešte viaže metóda clearRect()
, ktorá vymaže obsah plátna na
danej ploche. Parametre má rovnaké ako dve vyššie spomínané metódy. Aký
je však rozdiel medzi clearRect()
a fillRect()
, keď
nastavíme výplň na bielu? Plátno totiž v predvolenom stave nie je biele,
ale je priehľadné. Ak teda vymažeme plátno pomocou fillRect()
,
síce uvidíme bielu plochu, ale neuvidíme pozadia plátna a to čo bolo pod
plátnom.
Obdĺžnik v ceste
Poslednou možnosťou ako vykresliť obdĺžnik ich vložiť ho do cesty.
Hoci by sa to na prvý pohľad mohlo zdať zbytočné, keď máme metódy
fillRect()
a strokeRect()
, tak je to veľmi výhodné,
keď chceme vyfarbiť obdĺžnik a dať mu zároveň rámček. Jednoducho
obdĺžnik vykreslíme ako cestu, vykreslíme obsah a rámček.
kontext.beginPath(); kontext.rect(10, 10, 60, 60); kontext.closePath(); kontext.fillStyle = "red"; kontext.strokeStyle = "blue"; kontext.stroke(); kontext.fill();
výsledok:
Transformácie kontextu
Veľmi dôležité sú pri spracovávaní obrázku transformácie. Čas od
času sa bude hodiť, keď pozície nula nebude nulou. Asi ten najjednoduchší
prípad je, keď okolo canvasu budeme mať nejaký veľa špecifický 10px
široký rámik, ktorý by sme len v CSS nenastylovali. Samozrejme všade
môžeme vypisovať, aby sa vykresľovali na x + 10
,
y + 10
, ale jednoduchí pre nás bude využiť posunu kontextu. U
rotáciou to bude o to zaujímavejšie a mnohokrát jediná cesta ako docieliť
daného výsledku.
Uloženie kontextu
Pred akoukoľvek manipuláciou s kontextom je dobré si ho uložiť. My ho
síce potom môžeme vrátiť do pozície x -10 ay -10, ale je to zbytočne
pracné a navyše si musíme pamätať tieto hodnoty. Preto má kontext metódy
save()
a restore()
, ani jedna nepožaduje žiaden
parameter. Metóda save()
si uloží aktuálne transformácie a
metóda restore()
je obnoví.
Ako príklad si vykreslíme obrázok s červeným rámčekom, hoci je toto najjednoduchšie riešiť s pomocou CSS, skúsime to v JavaScripte.
Najprv si načítame plátno, kontext a obrázok, to už zvládnete sami.
Kontexte nastavíme farbu výplne napr. Na červenú a prekreslíme jej celý
<canvas>
. Potom kontext uložíme.
kontext.fillStyle = "#f00"; kontext.fillRect(0, 0, 510, 340); kontext.save();
Posun kontextu
Posun kontexte vykonávame metódou translate()
, ktorá prijíma
parametre x
a y
pre súradnice posunu. Nový nulový
bod bude na týchto súradniciach. My si plátno posunieme o kladných 10px ako
po osi x, tak po osi y.
kontext.translate(10, 10);
Teraz na pozíciu [0; 0] vykreslíme obrázok a kontext plátna obnovíme.
kontext.drawImage(obrazek, 0, 0); kontext.restore();
Keď si teraz aplikáciu otvoríme, všimneme si, že hoci sme zadali, nech sa obrázok nakreslí na [0; 0], tak sa vykreslil na [10; 10]. Môže za to práve náš posun.
Nezabudnite vrátiť kontext, keby ste s ním ešte niekedy potrebovali pracovať.
Zväčšenie / zmenšenie
Kontext môžeme zmenšovať a zväčšovať. Slúži na to metóda
scale()
, ktorá ako parametre prijíma násobky skutočné hodnoty
pre súradnice X a Y. Pre zmenšovanie sa zadávajú desatinné čísla menšie
ako 1.
Rotácie
Posledný operácií je rotácia. Často potrebujeme niečo otočiť. Napr.
keď potrebujeme urobiť kosoštvorec alebo kosodĺžnik, nie je nič
jednoduchšie ako otočiť kontext. Samozrejme by sme mohli body
prepočítavať, ale bolo by to zbytočne komplikované. Kontext otáčame
metódou rotate()
, ktorá ako parameter prijíma uhol v
radiánoch.
kontext.save(); kontext.translate(100, 100); kontext.rotate(45 * Math.PI / 180); kontext.strokeRect(0, 0, 50, 50); kontext.restore();
výsledok:
Tieň
Všetky operácie, ktoré niečo na canvas nakreslí, môžeme vykonávať s
tieňom. Vlastnosťou shadowColor
nastavíme farbu tieňa.
Vlastnosťami shadowOffsetX
a shadowOffsetY
nastavíme
posun tieňa a pomocou shadowBlur
ako veľmi bude rozostrený.
kontext.shadowColor = "red"; kontext.shadowOffsetX = 6; kontext.shadowOffsetY = 3; kontext.shadowBlur = 10;
výsledok:
Farebné prechody
Občas sa hodí obrázok "vylepšiť" farebnými prechodmi. Existujú 2 typy prechodov - lineárne a kruhové (radiálne). Obaja sa dajú nastaviť ako pre výplň, tak pre obrys.
Lineárny prechod
Lineárny prechod je jednoduchý, farby sa postupne mení ako povieme a to za
sebou. Vytvára sa metódou createLinearGradient()
na objekte
kontextu a odovzdávame jej 4 parametrami. Sú to súradnice x
a
y
pre začiatok a pre koniec gradientu. Novovzniknutý objekt
disponuje metódou addStopColor()
, ktorá pridá gradientu ďalšiu
farbu. Táto metóda prijíma ako prvý parameter pozíciu "zastavenie" v
rozmedzí 0
- 1
a ako druhý danú farbu.
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ýsledok:
Radiálne prechod
Radiálne čiže kruhový prechod sa používa úplne rovnako, len vytvorí
iný efekt. Metóda, ktorá ho vytvorí, sa nazýva
createRadialGradient()
a prijíma 6 parametrov. x
a
y
pre počiatočný bod, polomer a to všetko ešte raz aj pre
koncový bod.
V hodnotách je pomerne zmätok. Prvá pozícia x
a
y
je vlastne stred, prvý polomer je polomer, u ktorého začne
prechod. Pokiaľ bude nula, prechod začne už od stredu. Ak čokoľvek iné,
bude od stredu prvej farba a až na zadanom polomere začne prechádzať.
Pokiaľ chcete docieliť pravidelného kruhu, tak 4. a 5. parameter bude
kopírovať prvý a druhý. Šiesty parameter potom udáva na akom polomere sa
prechod zastaví, ďalej už bude len posledná farba. Nastavovanie farieb je
rovnaké.
Obrázková výplň
Jedna z ďalších možností výplne (dostupná aj pre obrys) je obrázková
výplň. Docielime jej tak, že vytvoríme pattern (vzor) a ten nastavíme
výplni (alebo obrysu). Pattern vytvoríme metódou
createPattern()
, kde ako prvý parameter odovzdáme obrázok a ako
druhý spôsob opakovaní. Pre opakovanie po osi X
aj
Y
môžeme ponechať prázdny String
.
let vzor = kontext.createPattern(obrazek, ""); kontext.fillStyle = vzor;
výsledok:
Ako vzor môžeme použiť aj iný element <canvas>
.
Práca s pixely
Až doteraz za nás nejaké pixely riešil JavaScript, ale občas sa hodí, aby sme aj my mohli pracovať s jednotlivými pixely.
Obrázková dáta
2D kontext plátna poskytuje objekt ImageData
. Získame ho
metódou getImageData()
, ktoré ako parametre odovzdáme súradnice
ľavého horného rohu a veľkosť výrezu. Tento objekt bude mať pole
data
, v ktorom sú všetky RGBA hodnoty pixelov v tomto výbere.
Pixely sú radené postupne, riadok po riadku, zľava doprava.
Vytvorme si aplikáciu, ktorá invertuje farby obrázka. Načítame si zas plátno, kontext a obrázok. Na plátno vykreslíme obrázok az obrázku si získame obrázková dáta.
kontext.drawImage(img, 0, 0); let dataObrazku = kontext.getImageData(0, 0, platno.width, platno.height);
Teraz cyklom prejdeme všetky farby, každý pixel je v poli zastúpený 4 ×, respektíve každá jeho zložka (R, G, B, A) tam má hodnotu. Cyklus teda nebude mať klasickú inkrementácia, ale iteračné premennú zvýšime o 4.
for (let i = 0; i < dataObrazku.data.length; i += 4) { }
V cykle potom hodnotám i
(R), i + 1
(G),
i + 2
(B) nastavíme novú farbu. V našom prípade odčítame
hodnotu farby od 255
, čo je maximálna hodnota. Tým hodnoty
otočíme a docielime efektu negatívu. Alfa kanál nebudeme meniť.
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];
Nakoniec vložíme upravená ImageData
do obrázka metódou
putImageData()
na pozíciu [0; 0].
kontext.putImageData(dataObrazku, 0, 0);
výsledok:
Teraz by ste už mali byť schopní ovládať <canvas>
v
JavaScripte. Odporúčam vyskúšať si cvičenie. V budúcej lekcii, Riešené úlohy k 14. a 15. lekcii JavaScriptu ,
sa pozrieme na časovača a animácie.
V nasledujúcom cvičení, Riešené úlohy k 14. a 15. lekcii JavaScriptu, si precvičíme nadobudnuté skúsenosti z predchádzajúcich lekcií.
Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.
Stiahnuť
Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami
Stiahnuté 895x (376.69 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript