Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

26. diel - 2D kontext plátna v JavaScripte

V minulej lekcii, Štylovanie obrázkov a vloženie textu na plátno v JavaScripte , sme sa naučili obrázky na plátne štylovať a ukázali sme si, ako vkladať na canvas externé obrázky alebo text.

V dnešnom JavaScript tutoriálu sa pozrieme podrobnejšie na kontext plátna. Naučíme sa ho posúvať, pretáčať alebo meniť jeho veľkosť. Ukážeme si aj ďalšie farebné efekty ako je pridanie tieňa alebo farebná výplň obrázkov.

Transformácia kontextu

Veľmi dôležité sú pri spracovávaní obrázku transformácie. Predstavme si, že chceme obrázku nastaviť veľmi špecifický napríklad 10 pixelov široký rámček, ktorý by sme len v CSS nenaštýlovali. Samozrejme všade môžeme vypisovať, aby sa vykresľoval na pozícii x + 10, y + 10, ale jednoduchšie je využiť posun kontextu.

Uloženie kontextu

Pred akoukoľvek manipuláciou s kontextom si ho uložíme. Mohli by sme ho síce neskôr vrátiť do pozície x - 10 a y - 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 žiadny parameter. Metóda save() si uloží aktuálny stav kontextu a metóda restore() ho obnoví.

Ako príklad si vykreslíme obrázok s červeným rámčekom. Do tela HTML súboru doplníme obrázok a plátno o trochu väčší ako obrázok:

<img src="foto.jpg" id="obrazek" />
<canvas id="platno" width="510" height="340"></canvas>

Potom si načítame plátno, kontext a obrázok. Kontexte nastavíme farbu výplne na červenú a prekreslíme ju celý <canvas>. Kontext metódou save() uložíme:

let platno;
let kontext;
let obrazek;

window.onload = function () {
    platno = document.getElementById("platno")
    kontext = platno.getContext("2d");
    obrazek = document.getElementById("obrazek");
    obrazek.parentElement.removeChild(obrazek);

    // Sem neskôr vložíme metódu scale() na zmenšenie obrázku

    kontext.fillStyle = "red";
    kontext.fillRect(0, 0, 510, 340);
    kontext.save();

    // Tu vzápätí doplníme zostávajúci kód
}

Posun kontextu

Posun kontextu 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 10 px ako po osi x, tak po osi y a na novej pozícii vykreslíme obrázok. Kontext plátna potom obnovíme:

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

V prehliadači vidíme, že sa obrázok nakreslil na pozíciu [10;10], aj keď sme na vykreslenie zadali pozíciu [0;0]. Môže za to práve náš posun:

Plátno
localhost

Zväčšenie a zmenšenie kontextu

Kontext môžeme tiež zmenšovať a zväčšovať. Slúži na to metóda scale(), ktorá ako parametre prijíma násobky skutočnej hodnoty pre súradnice x a y. Na zmenšovanie sa zadávajú desatinné čísla menšie ako 1. Doplňme do predchádzajúcej ukážky pred vykreslením obrázku tento riadok:

kontext.scale(0.5, 0.5);

Obrázok je teraz v prehliadači polovičný:

Plátno
localhost

Rotácia

Poslednú transformáciu kontextu predstavuje rotácia. Tú si vyskúšame opäť na štvorci, ktorý otočíme o 45 stupňov metódou rotate(). Tá ako parameter prijíma uhol v radiánoch. V ukážke najprv kontext uložíme, potom metódou translate() nastavíme posun, aby sme vykreslili otočený štvorec celý. Doplníme metódu na pretočenie kontextu, vykreslíme náš štvorec a kontext obnovíme:

kontext.save();
kontext.translate(100, 100);

// Rotácia o 45 stupňov prevedených na radiány
kontext.rotate(45 * Math.PI / 180);

kontext.strokeRect(0, 0, 50, 50);
kontext.restore();

Výsledok:

Plátno
localhost

Mazanie plátna

Okrem vykreslenia obrázku budeme určite niekedy chcieť vybraný obrázok alebo obsah celého plátna zmazať. Môžeme použiť metódu fillRect() a prekresliť plátno na bielo. Vhodnejšie je však použiť metódu clearRect(), ktorá vymaže obsah plátna na danej ploche. Parametre má rovnaké ako metóda fillRect().

Plátno totiž vo východiskovom stave nie je biele, ale je priehľadné. Pokiaľ teda vymažeme plátno pomocou fillRect(), síce uvidíme bielu plochu, ale neuvidíme, čo bolo pod plátnom.

Aby sme videli rozdiel medzi spomínanými metódami, vložíme do tela HTML <div> so žltým pozadím a plátnu nastavíme absolútnu pozíciu, aby ho čiastočne prekrývalo. Plátnu doplníme čierny rámček:

<div id="podklad" style="width: 200px; height: 200px; background-color: yellow;"></div>
<canvas id="platno" width="200" height="200" style="border: 1px solid black; position: absolute; left: 30px; top: 30px;"></canvas>

V JavaScripte na plátne namaľujeme dva štvorce:

window.onload = function() {
let platno = document.getElementById("platno");
let kontext = platno.getContext("2d");

kontext.fillRect(20, 40, 30, 30);
kontext.fillRect(70, 40, 30, 30);
};

Výsledok v prehliadači:

Plátno
localhost

Teraz zavoláme metódu fillRect() a prefarbíme ľavý štvorec bielou farbou. Druhý štvorec vymažeme metódou clearRect():

kontext.fillStyle = "white";
kontext.fillRect(20, 40, 30, 30);

kontext.clearRect(70, 40, 30, 30);

Výsledok:

Plátno
localhost

Keby sme chceli vymazať celé plátno, zmeníme posledný riadok takto:

kontext.clearRect(0, 0, platno.width, platno.height);

Tieň

Obrázkom na plátne môžeme pridať tieň. Vlastnosťou shadowColor nastavíme farbu tieňa, vlastnosťami shadowOffsetX a shadowOffsetY nastavíme posun tieňa a pomocou shadowBlur určíme, ako veľmi bude tieň rozostrený:

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

kontext.strokeRect(10, 10, 50, 50);

Výsledok:

Plátno
localhost

Farebné prechody

Obrázkom okrem tieňa môžeme tiež doplniť lineárne alebo kruhové farebné prechody. Oba sa dajú nastaviť ako pre výplň, tak aj pre obrys.

Lineárny prechod

Lineárny prechod vytvoríme pomocou metódy createLinearGradient() na objekte kontextu. Odovzdávame jej štyri parametre. Sú to súradnice x a y pre začiatok a pre koniec gradientu.

Novovzniknutý objekt disponuje metódou addColorStop(), ktorá pridá gradientu ďalšiu farbu. Táto metóda prijíma ako prvý parameter pozíciu "zastavenia" v rozmedzí 0 - 1 a ako druhý danú farbu. Objekt s takto nastaveným farebným prechodom odovzdáme ako vlastnosť fillStyle alebo strokeStyle:

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:

Plátno
localhost

Radiálny prechod

Radiálny alebo kruhový prechod sa používa úplne rovnako, len vytvorí iný efekt. Vytvoríme ho metódou createRadialGradient(), ktorá prijíma šesť parametrov. Súradnice 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, pri ktorom začne prechod. Pokiaľ bude hodnota tohto polomeru 0, prechod začne už od stredu. Pokiaľ uvedieme čokoľvek iné, bude od stredu prvá farba a až na zadanom polomere začne prechádzať v inú.

Ak chceme docieliť pravidelný kruh, tak štvrtý a piaty parameter bude kopírovať hodnoty prvého a druhého parametra. Šiesty parameter potom udáva, na akom polomere sa prechod zastaví. Nastavovanie farieb je rovnaké ako u lineárneho gradientu:

let gradient = kontext.createRadialGradient(50, 50, 0, 50, 50, 75);

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:

Plátno
localhost

Obrázková výplň

Ďalšia možnosť, ako spestriť naše obrázky, predstavuje obrázková výplň. Docielime ju tak, že vytvoríme pattern (vzor) a ten nastavíme vlastnosti fillStyle. Vzor vytvoríme metódou createPattern(), ktoré ako prvý parameter odovzdáme obrázok. V druhom parametri nastavujeme spôsob opakovania. Máme na výber zo štyroch hodnôt:

  • repeat alebo prázdny reťazec "" – na vyplnenie po osi x a y,
  • repeat-x – pre horizontálnu výplň,
  • repeat-y – pre vertikálnu výplň,
  • no-repeat – výplň sa nebude opakovať.

Obrázok načítame v tele HTML:

<img src="vzor.png" id="obrazek"/>

Počkáme, kým sa obrázok načíta a metódou createPattern() vytvoríme vzor výplne. Nový vzor nastavíme vlastnosti fillStyle a vykreslíme vyplnený štvorec:

window.onload = function() {
    let platno = document.getElementById("platno");
    let kontext = platno.getContext("2d");
    let obrazek = document.getElementById("obrazek");
    document.body.removeChild(obrazek);

    let pattern = kontext.createPattern(obrazek, "repeat");
    kontext.fillStyle = pattern;
    kontext.fillRect(50, 50, 100, 100);
};

Výsledok:

Plátno
localhost

Týmto sme si zhrnuli základné možnosti práce s plátnom a jeho kontextom v JavaScripte. Príklady si skúste upraviť a vyskúšajte si, ako uvedené metódy a vlastnosti s inými parametrami menia vzhľad obrázkov. Využijete ich aj pri cvičení, ktoré má tento kurz k dispozícii.

V nasledujúcom cvičení, Riešené úlohy k 23.-26. lekciu 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é 901x (376.69 kB)
Aplikácia je vrátane zdrojových kódov v jazyku JavaScript

 

Predchádzajúci článok
Štylovanie obrázkov a vloženie textu na plátno v JavaScripte
Všetky články v sekcii
Základné konštrukcie jazyka JavaScript
Preskočiť článok
(neodporúčame)
Riešené úlohy k 23.-26. lekciu JavaScriptu
Článok pre vás napísal Michal Žůrek - misaz
Avatar
Užívateľské hodnotenie:
2 hlasov
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