Začínáme s HTML5 canvasem

Canvas je pravděpodobně jednou z nejrevolučnějších značek HTML5. V dnešním článku si tuto značku představíme a naučíme se její základní použití. Ukážeme, jak pomocí ní kreslit základní geometrické útvary přímo do webové stránky.
Tento článek je překladem anglického originálu vydaného na Dev.Opera. Autorem původního textu je Mihai Sucan.
Úvod
Specifikace HTML5 obsahuje řadu nových vlastností, jednou z nich je značka canvas
. HTML 5 canvas
vám nabízí snadnou možnost kreslení grafiky pomocí JavaScriptu. V každé značce canvas
můžete použít „context“, jehož javascriptové metody nakreslí cokoliv chcete. Prohlížeče mohou implementovat více contextů s rozličnými API.
Většina prohlížečů implementovala 2D context canvasu – Opera, Firefox, Chrome a Safari (IE canvas nepodporuje, ale většina API canvasu je v něm snadno emulovatelná pomocí VML – pozn. překl.). Existuje také experimentální build Opery s implementací 3D contextu a rozšíření, které přidá podporu 3D contextu do Firefoxu:
- Build Opery s 3D canvasem, HTML videm a podporou File I/O
- Více o používání 3D contextu v Opeře
- Více o 3D contextu ve Firefoxu.
Tento článek vás provede základy 2D contextu canvasu, používáním základních funkcí včetně čar, tvarů, obrázků, textu a dalších. Budeme předpokládat, že znáte základy JavaScriptu.
Základy používání canvasu
Použití canvasu na vaší stránce je velmi jednoduché, stačí přidat značku <canvas>
do vašeho HTML, např.:
<canvas id="myCanvas" width="300" height="150">
Fallback content (náhradní obsah) pro prohlížeče, které canvas nepodporují.
</canvas>
Definovali jsme id elementu, abychom se na něj mohli snadno odkazovat z JavaScriptu a také jsme definovali jeho šířku a výšku. Tím jsme si vytvořili kreslící plochu. Pojďte si něco nakreslit.
Pro kreslení do canvasu budeme potřebovat JavaScript. Nejprve vytvoříme referenci na náš canvas pomocí getElementById
a následně inicializujeme požadovaný context. Pak už můžeme začít kreslit do canvasu pomocí rozhraní contextu, který jsme inicializovali. Následující skript (živá ukázka) do našeho canvasu nakreslí jednoduchý obdélník:
// Odkaz na canvas
var elem = document.getElementById('myCanvas');
// Vždy kontrolujte dostupnost vlastností a metod, to aby skript skript
// v nějakém prohlížeči "nehavaroval".
if (elem && elem.getContext) {
// získáme 2d context.
// Zapamatujte si: pro jednu značku canvas můžete inicializovat jen 1 context.
var context = elem.getContext('2d');
if (context) {
// Nyní nakreslíme obdélník.
// Zadáme souřadnice x,y následované šířkou a výškou.
context.fillRect(0, 0, 150, 100);
}
}
Skript můžete vložit ho hlavičky vašeho dokumentu nebo do externího souboru, to je na vás.
API 2D contextu
Nyní, když jsme si vytvořili náš první příklad, se můžeme podívat na API 2D contextu hlouběji, ať vidíme, co máme k dispozici.
Kreslení čar
Pokud jste si prostudovali příklad výše, je pro vás jednoduché nakreslit obdélník jakékoliv barvy.
Pomocí vlastností fillStyle a strokeStyle snadno nastavíte, jaká barva bude použita pro vyplnění a jaká pro obrys. Můžete používat stejné hodnoty barev jako v kaskádových stylech: šestnáctkové kódy, rgb(), rgba() and dokonce hsla() pokud to prohlížeč podporuje (např. Opera 10 a Firefox 3).
Metoda fillRect
nakreslí vyplněný obdélník, metoda strokeRect
nakreslí obdélník bez výplně obsahující pouze obrysy. Pokud chcete vyčistit část canvasy, můžete použít metodu clearRect
. Všechny tyto tři metody používají stejné argumenty: x, y, width, height. První dva argumenty jsou souřadnice x, y, další dva argumenty jsou šířka a výška obdélníku.
Tloušťku pak nastavíme vlastností lineWidth. Podívejme se na příklad používající metody fillRect
, strokeRect
a clearRect
:
context.fillStyle = '#00f'; // modrá
context.strokeStyle = '#f00'; // červená
context.lineWidth = 4;
// Nakreslíme obdélníky.
context.fillRect (0, 0, 150, 50);
context.strokeRect(0, 60, 150, 50);
context.clearRect (30, 25, 90, 60);
context.strokeRect(30, 25, 90, 60);
Výstup tohoto příkladu najdete na obrázku 1.

Obr. 1: Ukázka použití fillRect, strokeRect a clearRect.
Cesty (paths)
Cesty vám umožní kreslit libovolné tvary. Napřed vyznačíte obrys, ten pak můžete vyplnit a nakreslit obrysovou čáru, pokud chcete. Vytvoření tvaru je jednoduché – na začátku zavoláte beginPath()
, následně nakreslíte cestu pomocí čar a dalších metod. Jakmile jste hotovi, zavoláte fill
a stroke
– pokud chcete tvar vyplnit nebo vykreslit obrysovou čáru. Na konci zavoláte metodu closePath()
.
Následuje příklad – tento kód nakreslí trojúhelník:
// Nastavení stylu
context.fillStyle = '#00f';
context.strokeStyle = '#f00';
context.lineWidth = 4;
context.beginPath();
// Začíná se v levém horním rohu
context.moveTo(10, 10); // souřadnice (x,y)
context.lineTo(100, 10);
context.lineTo(10, 100);
context.lineTo(10, 10);
// Hotovo. Nyní tvar vyplníme a nakreslíme obrys.
// Pozn.: vyznačený tvar nebude viditelný, dokud nezavoláte jednu z těchto dvou metod.
context.fill();
context.stroke();
context.closePath();
Výsledek bude stejný jako na obrázku 2.

Obr. 2: Trojúhelník.
Připravil jsem pro vás i komplikovanější cesty kombinující čáry, křivky a oblouky – jen se podívejte.
Vkládání obrázků
Metoda drawImage
vám dovolí vložit do vašeho canvasu obrázek (ze značek img
nebo canvas
). V Opeře můžete do canvasu nakreslit i SVG obrázky. (Metoda drawImage
je jednou z metod, kterou není možné emulovat v Internet Exploreru – pozn. překl.) Jedná se o komplikovanou metodu, která používá tři, pět nebo devět argumentů:
- Tři argumenty: základní použití
drawImage
obsahuje argument odkazující na vkládaný obrázek a dvě souřadnice obsahující místo vložení do vašeho contextu v canvasu. - Pět argumentů: o něco komplikovanější varianta
drawImage
obsahuje předchozí tři argumenty a navíc šířku a výšku vkládaného obrázku (pro případ, že chcete změnit jeho velikost). - Devět argumentů: nejkomplikovanější použití
drawImage
obsahuje předchozích pět argumentů a navíc dvě souřadnice uvnitř vkládaného obrázku a také šířku a výšku. Tuto variantu použijete, pokud chcete obrázek dynamicky oříznout před jeho vložením do canvasu.
Následující kód ukazuje všechny tři způsoby použití drawImage
:
// Tři argumenty: element, cílové souřadnice (x,y).
context.drawImage(img_elem, dx, dy);
// Pět argumentů: element, cílové souřadnice (x,y)
// a cílová šířka s výškou.
context.drawImage(img_elem, dx, dy, dw, dh);
// Devět argumentů: element, zdrojové souřadnice (x,y), šířka a výška pro oříznutí,
// cílové souřadnice a cílová šířka s výškou (pro změnu velikosti).
context.drawImage(img_elem, sx, sy, sw, sh, dx, dy, dw, dh);
Výsledek bude vypadat jako na obrázku 3.

Obr. 3: Příklad použití drawImage
.
Pokračování příště
To není všechno. Příště vás seznámíme s dalšími možnostmi canvasu, jakou je práce s pixely, textem a používání gradientů.
Tento článek je překladem textu HTML 5 canvas – the basics, jehož autorem je Mihai Sucan a je zde zveřejněn s laskavým svolením Opera Software.
"Začínáme z HTML5 canvasem"
s kým čím?
(po opravě smažte)
Taky me to hned bouchlo do oci :-)
Byl to samozřejmě nesmysl.
super
Myslíte, že bude mať canvas niekedy praktické využitie?
Mňa zatiaľ nič nenapadlo, možno nejaké vykresľovanie grafov a podobne, ale veď to už sa dá aj inak
Canvas se pouziva tak posledni rok dva a vyuziti rozhodne ma. "tohle by slo delat i jinak" neni sam o sobe argument pro (ne)rozsireni nejake technologie, viz konkurence, ktere na trhu panuji.
To s tým "inak" som myslel tak, že aké výhody (oproti iným technológiám) so sebou prináša canvas?
Prostredníctvom canvasu nie je možná interakcia užívateľa (ak sa nemýlim), predstavujem si ho ako vygenerovaý obrázok.
:-) viz napr. http://www.benjoffe.com/code/demos/interpolate/
Skvelé! Presne niečo takéto som potreboval vidieť, ďakujem :)
"Tuším", že som sa s tou interakciou mýlil, teraz pre mňa canvas naberá úplne iný rozmer
Tak nevim, ale proc to neudelat radeji pomoci SVG?
Možná, protože to většině uživatelů nebude fungovat.
Prostredníctvom canvasu nie je možná interakcia užívateľa
Jedná se o HTML značka. Každá taková značka umožňuje interakci s uživatelem, stačí ji naskriptovat.
No s tím skriptováním měl ovšem kolega výše tak trochu pravdu. Interakce je dost omezená a veškeré události myši musí člověk počítat ručně. Např. mapka s hovery nad jednotlivými oblastmi se canvasem dělá dost neohrabaně. V tomto je lepší SVG (pokud není potřeba zrovna vysoký výkon).
Interakce je dost omezená a veškeré události myši musí člověk počítat ručně
Jenom v případě, že nepoužije nějaký framework a ty vznikají. Ještě to je v průběhu evoluce, není to rozhodně dokonalé, dal bych tomu tak rok, možná dva, ale pak bych se jakékoliv „omezenosti“ a ručního počítání neobával.
To je pravda. Ale dneska je canvas hrozně módní a mám pocit, že hype kolem canvasu trochu zastiňuje SVG, které se na mnohé aplikace hodí lépe. Pak se dostáváme k paradoxním situacím, kdy emulujeme interakce myši nad cavasem pomocí javascriptu, přičemž canvas v IE emulujeme pomocí ExCanvasu, který vnitřně používá VML, které vlastně tyto události umí nativně :) V tomto případě mi přijde vhodnější např. i zde na zdrojáku popisovaná knihovna Raphael. Samozřejmě je možné, že u nativního canvasu a rychlého JS se i u té emulace dostaneme i na vyšší rychlost, než u nativního SVG. Vždycky je dobré zvážit, co je pro daný účel vhodnější.
Všechno má své příčiny. Canvas se začal tak masivně používat protože je to řešení, které dnes funguje. Nějaké skryté procesy probíhající uvnitř (třeba ta emulace) nikoho nezajímají (a nikdy u takových technologií nikoho nezajímaly) – na (ne)rozšíření nebudou mít vliv, počítá se to, co funguje. Váhy se můžou jednoho dne změnit, může přijít dostatečná podpora SVG. Ale v tuto chvíli evoluce přeje canvasu. Podobně jako dnes vládnou zemi jistí savci chodící po dvou nohou – kdysi to bylo jinak a za pár tisíc let to může být rovněž jinak, ale v tuhle chvíli jsou váhy nastavené takhle – pro lidi i pro canvas. Můžete se přít, že jiné řešení by bylo lepší, ale dokud se nezmění podmínky prostředí, bude to jen teoretizování.
Dosud jsem se vůbec nepřel, ale nyní asi začnu. Canvas i SVG mají dnes prakticky stejnou podporu – obě technologie naráží na nepodporu v IE, kde jsou obě omezené na emulaci pomocí SVG. Nejde tedy o žádné teoretizování – jak canvas, tak SVG jsem již několikrát použil na reálných webech – vždy pomocí podpůrných knihoven pro IE. Není pravda, že skryté procesy nikoho nezajímají. Naopak, v praxi člověk obvykle narazí na bugy nebo omezení z těchto emulací vyplývající a musí je nějakým způsobem řešit. Ovšem canvas a SVG si navzájem nekonkurují, naopak se můžou dobře doplňovat – a to jsem se snažil v předchozích příspěvcích sdělit.
Mělo tam být samozřejmě "emulací pomocí VML"…
Není pravda, že skryté procesy nikoho nezajímají.
Řekněme, že dokud vše funguje, tak zcela zanedbatelnou menšinu vývojářů. Pokud vše nefunguje, tak se dané technologii raději všichni vyhnou (opět až na zanedbatelnou menšinu).
tak SVG jsem již několikrát použil
Pomocí Raphaëla nebo něčeho jiného?
Ovšem canvas a SVG si navzájem nekonkurují, naopak se můžou dobře doplňovat
Můžou se doplňovat, ale je řada styčných ploch, kde si budou konkurovat – ale to je dobře. Konkurence je potřeba i v technologiích, pomáhá vývoji.
Ano, pomocí Raphaël, ale stejný princip používá již déle např. dojo.gfx.
Na jednej strane je to pekné, na druhej strane nevidím veľké využitie takéhoto grafu. Normálne v grafe ukazujem výsledky, ku ktorým som došiel, neprezentujem graf, aby si ho každý mohol pohýbať. Dokonca aj pre výukové účely je často lepšia nejaká animácia (stačí aj GIF) alebo priloženie viacerých obrázkov ilustrujúcich mnou zvolené situácie.
Toto sa mi zdá vhodné len na nejaké srandičky, ako nosič informácie si to predstaviť stále nedokážem.
Ale to neznamená, že neexistuje. Téměř denně s nějakými interaktivními grafy pracuji (např. v Google Analytics, Facebooku), s obrázkovou náhradou bych rozhodně nebyl tak produktivní. A našli bychom řadu odvětví, kde se všechny informace obsažené v grafu do jednoho obrázku prostě nevejdou (což se obchází např. tak, že vám nabízí zdrojová data ke stažení), tam interaktivní řešení rozhodně přijde vhod.
Ja sa len snažím nejaké využitie nájsť. :-)
Je možné pomocou canvas vytvoriť aj taký graf, ktorý by sa prekresľoval tým, že by som menil vstupné dáta, alebo naopak, hýbaním krivky by sa mi zobrazovali vstupné dáta? Ale to by zas bolo využiteľné len pre výukové účely. Možno na to hľadím nesprávne, ale som zvyknutý publikovať trebárs vedecké články, a tam väčšinou presne viem, čo chcem čitateľovi ukázať a nebýva toho ani tak veľa, že by to nešlo obrázkami – tie zosnímam trebárs ako screenshoty zo štatistického programu alebo z grafického programu. Možno byt bolo výhodné, ak by som tvrdil, že som objavil nejakú rovnicu, ktorá sa dá využiť v praxi a užívateľ by si mohol skúšať rôzne kombinácie dát, či ma nenachytá…
Je možné pomocou canvas vytvoriť aj taký graf, ktorý by sa prekresľoval tým, že by som menil vstupné dáta, alebo naopak, hýbaním krivky by sa mi zobrazovali vstupné dáta?
To pochopitelně jde.
zvyknutý publikovať trebárs vedecké články
Tak kromě využití zmíněného výše bychom našli třeba některé spektometrické výstupy, které do obrázku už z principu přehledně umístit nejdou. Mít tam přístup může být skutečně žádoucí.
> možno nejaké vykresľovanie grafov a podobne, ale veď to už sa dá aj inak
A jak?
řekl bych, že svět existoval i před canvasem, ne?
Ano, treba generovani obrazku/grafu na serveru. Prijde vam to jako srovnatelne reseni? Canvas urcite sve uplatneni najde
Asi byly míněny grafy sloupcové pomocí pozicování. Pro čáry mě čistě HTML řešení nenapadá a to je dle mého mínění prostor pro canvas. Ikdyž jestli není lepší na takové věci potom využít spíše Flash(to asi je míněno tím jinak).
Proč by mělo být lepší místo Canvasu použít Flash?
Výhodu flashe spatřuji v tom, že je vektorový, a je k dispozici na 98% prohlížečích. Tudíž se na tvorbu grafů hodí o něco lépe(jednoduchý zoom a posun po ose). A co si budem nalhávat, vzhled grafu tam jde daleko více kontrolovat.
Osobně se ale nebráním Canvasu, protože to je přesně element který v HTML chyběl, pro jednoduché grafy ideální a kdo ví kam se dostane. Specifikace vypadá velmi dobře(a ten posun a zoom by měl umět nakonec taky).
http://www.whatwg.org/specs/web-apps/current-work/#canvas
A co si budem nalhávat, vzhled grafu tam jde daleko více kontrolovat.
To bude nějaký nesmysl. V obou případech se jedná pixelmapy, neexistuje příklad, který by šel nakresli ve Flashi a nešel v canvasu (a naopak).
To jsem ani netvrdil, že by něco ve Flashi šlo a v canvasu ne. Šlo mi o komfort. Práce s nimi je dost odlišná. Jde o to, že Flash je ze své podstaty vektorový, zatímco canvas je bitmapa, ke které jsou funkce, které dokáží vektorové chování napodobit, bohužel současná implementace není z nejideálnějších.
Také jde o to, že zatímco flash je zde již delší dobu a má lepší podporu v prohlížečích tak canvas je novinka, která se snaží vyplnit místo, která byla pro čisté (x)HTML nepřístupná, a za to jsem vděčen.
Bohužel, jistý majoritní prohlížeč se ani nesnaží zabudovat řádnou podporu do svého kódu. Je zde podobná situace, jako okolo SVG obrázků, keré by hravě dokázály canvas nahradit, alsepoň z hlediska již známých dat. Jak by to bylo hezké mít podporu pro tento formát, přičemž JScipt funkce by byly téměř identické. Bohužel si nelze dovolit si na tento luxus spoléhat.
Je zde podobná situace, jako okolo SVG
Situace s canvasem naštěstí není podobná tomu, jak to bylo s SVG (a díky Google za to), proto se také použití canvasu na webu rozšiřuje na rozdíl od SVG, které na něm řadu let stagnovalo. Lidé pohybující se okolo prohlížečů naštěstí už dávno přišli se strategií, jak se s opožděným vývojem IE vyrovnat a také to činí. To je důvod, proč se historie neopakuje.
Mělo by to tu výhodu, že to bude fungovat i bez javascriptu :)
A také nevýhodu, že to dnes nepůjde na reálném webu použít.
A canvas jako půjde použít? Ha ha ha, you are on the way to destruction…
Ano, půjde. V tom je ten rozdíl. V řadě případů zcela bez problému.
MSIE canvas „neumí“…
S Excanvasem ho celkem v pořádku umí.
pochopitelne bylo…. jenomze je posledni dobou modou znovuvynalezat kola (a delat je pritom sisata, protoze je to tak nejak kool)…
Neříkete, SVG umí interaktivitu bez Javascriptu? Totiž něco na způsob tohohle?
Ve vývojové verzi gnuplotu (4.3) byl nedávno implementován terminál canvas, "set term canvas", který generuje HTML5 kód pro vykreslení grafu, a to včetně některých myšoidních možností (zoom, popis bodů). Demo viz např. zde: http://skuld.bmsc.washington.edu/~merritt/gnuplot/canvas_demos/
Tak to je dobrá zpráva. Existují k tomu už zkompilované verze k vyzkoušení?
Muzete si prelozit vyvojovou verzi gnuplotu podle techto instrukci:
http://gnuplot.sourceforge.net/development/index.html#DownloadCVS
nebo si stahnout prelozenou binarku pro Wokna:
http://gnuplot.sourceforge.net/development/binaries/
http://www.tatsuromatsuoka.com/gnuplot/Eng/winbin/
Děkuji, tu adresu na Sourcefoge jsem už zkoušel, ale tam jsou jen staré verze, každopádně ten Japonec má zdá se aktuální.
chyti rybar morskou pannu, chvili na ni cumi a pak ji hodi zpatky, druhy se ho pta: Proc ??, prvni odpovi: Jak ??
toz asyk tak s tim canvasem…
A.