NOVINKA - Vstup do světa AI s ONLINE víkendovým kurzem Práce s umělou inteligencí od A do Z. Přihlas se ještě dnes!
NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.

Lekce 27 - Transformace kontextu plátna v JavaScriptu

V minulé lekci, Stylování obrázků a vložení textu na plátno v JavaScriptu, jsme se naučili obrázky na plátně stylovat a ukázali jsme si, jak vkládat na canvas externí obrázky nebo text.

V dnešním JavaScript tutoriálu se podíváme podrobněji na kontext plátna. Naučíme se jej posouvat, přetáčet nebo měnit jeho velikost. Ukážeme si také další barevné efekty, jako je přidání stínu nebo barevná výplň obrázků.

Transformace kontextu

Velmi důležité jsou při zpracovávání obrázku transformace. Představme si, že chceme obrázku nastavit hodně specifický, například 10 pixelů široký rámeček, který bychom jen v CSS nenastylovali. Samozřejmě všude můžeme vypisovat, aby se vykresloval na pozici x + 10, y + 10, ale jednodušší je využít posunu kontextu.

Uložení kontextu

Před jakoukoliv manipulací s kontextem je vhodné jej uložit. Mohli bychom ho sice později vrátit do pozice x - 10 a y - 10, ale je to zbytečně pracné a navíc si musíme pamatovat tyto hodnoty. Práci nám usnadní metody:

  • save() - pro uložení aktuálního stavu kontextu,
  • restore() - pro obnovení uloženého stavu.

Ani jedna z těchto metod nepožaduje žádný parametr.

Jako příklad si vykreslíme tento obrázek s červeným rámečkem:

Obrázek mostu - Základní konstrukce jazyka JavaScript

Obrázek uložíme pod názvem foto.png do složky projektu. Připravíme HTML dokument, do jehož těla vložíme obrázek, plátno o něco větší než samotný obrázek, a element <script>:

<!DOCTYPE html>

<html lang="cs-cz">
    <head>
        <meta charset="utf-8" />
        <title>Plátno</title>
    </head>

    <body>
        <img src="foto.png" alt="Most" id="obrazek" />
        <canvas id="platno" width="510" height="340"></canvas>
        <script src="script.js"></script>
    </body>
</html>

Ve Windows najdeme rozměry po kliknutí pravým tlačítkem na obrázek v nabídce Vlastnosti v záložce Podrobnosti. Na Macu použijeme možnost Získat informace (Command + I)

Ve složce s projektem vytvoříme soubor script.js a dopíšeme do něj následující kód:

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 později vložíme metodu scale() pro zmenšení obrázku

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

    // Zde vzápětí doplníme zbývající kód
}

Načetli jsme do proměnných plátno, kontext a obrázek. Kontextu jsme nastavili červenou barvu výplně a překreslili jí celý <canvas>. Metodou removeChild() jsme obrázek odstranili z dokumentu, aby se nám po jeho vykreslení JavaScriptem nezobrazil dvakrát. Nakonec jsme kontext uložili metodou save().

Posun kontextu

Posun kontextu provádíme metodou translate():

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

Metoda přijímá parametry x a y pro souřadnice posunu. Nový nulový bod bude na těchto souřadnicích. My jsme plátno posunuli o kladných 10 px jak po ose x, tak po ose y a na nové pozici vykreslili obrázek. Kontext plátna jsme pak obnovili.

V prohlížeči vidíme, že se obrázek nakreslil na pozici [10;10], i když jsme pro vykreslení zadali pozici [0;0]. Může za to právě náš posun:

Plátno
localhost

Zvětšení a zmenšení kontextu

Kontext můžeme také zmenšovat a zvětšovat. Slouží k tomu metoda scale():

kontext.scale(0.5, 0.5);

Metoda 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ž jedna.

Obrázek je nyní v prohlížeči poloviční:

Plátno
localhost

Rotace

Poslední transformací kontextu je rotace. Z HTML dokumentu odstraníme obrázek (celý element <img>) a v JavaScriptu ponecháme pouze načtené plátno a kontext:

let platno = document.getElementById("platno");
let kontext = platno.getContext("2d");

Pro všechny následující příklady tyto dvě proměnné ponecháme a budeme měnit pouze kód za nimi.

Rotaci si vyzkoušíme opět na čtverci, který otočíme o 45 stupňů metodou rotate():

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

kontext.rotate(45 * Math.PI / 180);

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

Metoda rotate() přijímá jako parametr úhel v radiánech. V příkladu jsme nejprve uložili aktuální stav kontextu, poté jsme pomocí metody translate() nastavili posun, aby se otočený čtverec zobrazil celý. Následně jsme použili metodu rotate() pro otočení kontextu. Protože parametr vyžaduje úhel v radiánech, bylo potřeba úhel ze stupňů převést. Poté jsme čtverec vykreslili a nakonec obnovili původní stav kontextu:

Plátno
localhost

Mazání plátna

Kromě vykreslení obrázku budeme určitě někdy chtít vybraný obrázek nebo obsah celého plátna smazat. Můžeme použít metodu fillRect() a překreslit plátno na bílo. Plátno ale ve výchozím stavu není bílé, je průhledné. Pokud tedy překreslíme plátno pomocí fillRect(), sice uvidíme bílou plochu, ale neuvidíme, co bylo pod plátnem. Vhodnější je tedy použít metodu clearRect():

kontext.fillRect(0, 0, 200, 200);
kontext.clearRect(10, 10, 100, 100);

Nejprve jsme vytvořili černý čtverec metodou fillRect() a následně vymazali jeho část pomocí metody clearRect(). Parametry mají obě metody stejné - první dva určují souřadnice levého horního rohu, třetí parametr představuje šířku a čtvrtý výšku dané oblasti:

Plátno
localhost

Kdybychom chtěli vymazat celé plátno, změníme parametry metody při volání takto:

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

Stín

Obrázkům na plátně můžeme přidat stín:

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

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

Při nastavování použijeme vlastnosti:

  • shadowColor – pro nastavení barvy stínu,
  • shadowOffsetX – pro nastavení vodorovného posunu stínu,
  • shadowOffsetY – pro nastavení svislého posunu stínu,
  • shadowBlur – pro určení míry rozostření stínu.

Nakonec metodou strokeRect() vykreslíáme čtverec s nastaveným stínem:

Plátno
localhost

Barevné přechody

Obrázkům můžeme kromě stínu přidat také lineární nebo kruhový barevný přechod. Jde o způsob, jak vybarvit plochu více barvami, které na sebe postupně navazují. Přechody lze použít jak pro výplň, tak pro obrys.

Lineární přechod

Lineární přechod vytvoříme pomocí metody createLinearGradient() volané na objektu kontextu:

let prechod = kontext.createLinearGradient(0, 0, 100, 0);

Metoda přijímá čtyři parametry. První dva určují souřadnice x a y pro počáteční bod gradientu, druhé dva jeho koncový bod. Gradient jsme uložili do proměnné prechod.

Nyní můžeme pomocí metody addColorStop() přidat do gradientu další barvy:

let prechod = kontext.createLinearGradient(0, 0, 100, 0);

prechod.addColorStop(0, "yellow");
prechod.addColorStop(0.2, "orange");
prechod.addColorStop(0.4, "pink");
prechod.addColorStop(0.6, "red");
prechod.addColorStop(0.8, "green");
prechod.addColorStop(1, "blue");

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

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

Tato metoda přijímá jako první parametr pozici přidávané barvy v rozmezí od 0 pro začátek až po 1 pro konec přechodu. Druhý parametr určuje samotnou barvu. Přechod jsme použili k nastavení výplně pro vykreslované prvky pomocí vlastnosti fillStyle (podobně jako při nastavování barvy) a vykreslili jsme čtverec pomocí fillRect(). Nakonec jsme ještě do grafiky přidali metodou fillText() nápis ITnetwork.cz:

Plátno
localhost

Radiální přechod

Radiální neboli kruhový přechod se používá úplně stejně, jen vytvoří jiný efekt. Vytvoříme jej metodou createRadialGradient():

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

Tato metoda přijímá šest parametrů. První tři určují souřadnice x a y a poloměr počátečního bodu. Další tři určují souřadnice a poloměr koncového bodu.

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 hodnota tohoto poloměru 0, přechod začne již od středu. Pokud uvedeme cokoli jiného, bude od středu první barva a až na zadaném poloměru začne přecházet v jinou.

Jestliže chceme docílit pravidelného kruhu, tak čtvrtý a pátý parametr bude kopírovat hodnoty prvního a druhého parametru. Šestý parametr poté udává, na jakém poloměru se přechod zastaví. Nastavování barev je stejné jako u lineárního gradientu:

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

prechod.addColorStop(0, "yellow");
prechod.addColorStop(0.2, "orange");
prechod.addColorStop(0.4, "pink");
prechod.addColorStop(0.6, "red");
prechod.addColorStop(0.8, "green");
prechod.addColorStop(1, "blue");

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

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

Opět jsme využili vlastnost fillStyle a pomocí metody fillRect() vykreslili čtverec s nastaveným barevným přechodem. Tento přechod se pak automaticky použil i na text, který jsme vykreslili metodou fillText():

Plátno
localhost

Obrázková výplň

Další možnost, jak zpestřit naše obrázky, představuje obrázková výplň. Docílíme jí tak, že vytvoříme pattern (vzor) a ten nastavíme vlastnosti fillStyle. Vzor vytvoříme metodou createPattern(), které jako první parametr předáme obrázek. Ve druhém parametru nastavujeme způsob opakovaní. Máme na výběr ze čtyř hodnot:

  • repeat nebo prázdný řetězec "" – pro vyplnění po ose x a y,
  • repeat-x – pro horizontální výplň,
  • repeat-y – pro vertikální výplň,
  • no-repeat – výplň se nebude opakovat.

Pro náš vzor použijeme obrázek s otazníkem: Obrázek se vzorem - Základní konstrukce jazyka JavaScript

Ten si stáhneme, uložíme do složky s projektem a poté ho vložíme do těla HTML dokumentu doplněním následujícího kódu:

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

Do souboru script.js vložíme následující kód:

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

    let obrazek = document.getElementById("obrazek");
    document.body.removeChild(obrazek);

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

Kromě plátna a kontextu jsem si načetli náš obrázek a následně ho odstranili z dokumentu metodou removeChild(). Metodou createPattern() jsme vytvořili náš vzor a uložili ho do proměnné. Tu jsme potom nastavili jako hodnotu vlastnosti fillStyle. Následně jsme vykreslili metodou fillRect() vyplněný čtverec:

Plátno
localhost

Tímto jsme si shrnuli základní možnosti práce s plátnem a jeho kontextem v JavaScriptu. Příklady si zkuste upravit a vyzkoušejte si, jak uvedené metody a vlastnosti s jinými parametry mění vzhled obrázků. Využijete je také u cvičení, která má tento kurz k dispozici.

V následujícím cvičení, Řešené úlohy k 24.-27. lekci JavaScriptu, si procvičíme nabyté zkušenosti z předchozích lekcí.


 

Měl jsi s čímkoli problém? Stáhni si vzorovou aplikaci níže a porovnej ji se svým projektem, chybu tak snadno najdeš.

Stáhnout

Stažením následujícího souboru souhlasíš s licenčními podmínkami

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

 

Předchozí článek
Stylování obrázků a vložení textu na plátno v JavaScriptu
Všechny články v sekci
Základní konstrukce jazyka JavaScript
Přeskočit článek
(nedoporučujeme)
Řešené úlohy k 24.-27. lekci JavaScriptu
Článek pro vás napsal Michal Žůrek - misaz
Avatar
Uživatelské hodnocení:
943 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