Přejít k navigační liště

Zdroják » Webdesign » SVG, nebo Canvas? Vyberte si

SVG, nebo Canvas? Vyberte si

Články Webdesign

Pro vložení grafiky do stránky měli weboví vývojáři až donedávna v podstatě jen dvě možnosti – buď statický obrázek, nebo využít plugin (Flash, VML apod.) V poslední době doznal značného rozšíření ale vektorový formát SVG a bitmapový HTML5 canvas. Jaké jsou jejich vlastnosti a v čem se liší?

Úvod

Nové webové technologie jsou stále dostupnější ve všech prohlížečích, a pro ty, které je zatím neimplementují, existují náhradní řešení, jako např. Raphaёl pro SVG a ExCanvas pro Canvas. A když i Internet Explorer začal koketovat se SVG (a IE9 beta potvrdila, že to Microsoft myslí s podporou vážně), můžeme se v budoucnu těšit na větší podporu. Což ale způsobí další problém, který budeme muset řešit – totiž rozhodnout se, kterou technologii použít.

HTML5 CanvasSVG jsou technologie, které umožňují vložit do HTML stránek nějakou pokročilejší grafiku, ale jsou od základu rozdílné. V tomto článku si popíšeme rozdíly a znalosti, které vám pomůžou používat SVG a Canvas efektivně a hlavně na správném místě.

Pokud si chcete vyzkoušet zde uvedené kódy, můžete si stáhnout soubor s příklady z článku.

Scalable Vector Graphics

SVG je vektorový grafický formát založený na XML. Obsah může být statický, dynamický, interaktivní či animovaný – SVG je velmi flexibilní. Navíc můžete stylovat SVG pomocí CSS a dynamicky s ním pracovat SVG DOM. A vzhledem k tomu, že text v SVG je zapsán jako text, splňuje tak do jisté míry i požadavky na přístupnost. SVG můžete zapsat přímo do (X)HTML stránky pomocí elementu  object.

Zde je ukázka kruhu nakresleného pomocí SVG — obsahuje barevný přechod a jednoduchou animaci:

<svg version="1.1"
  width="320" height="320"
  xmlns="http://www.w3.org/2000/svg">
  <defs>
    <radialGradient id="circleGrad">
      <stop offset="0%"   stop-color="rgb(255, 255, 0)" />
      <stop offset="100%" stop-color="rgb(  0, 255, 0)" />
    </radialGradient>
  </defs>
  <ellipse fill="url(#circleGrad)" stroke="#000" cx="50%"
  cy="50%" rx="50%" ry="50%">
    <animate attributeName="rx" values="0%;50%;0%" dur="2s"
      repeatCount="indefinite" />
    <animate attributeName="ry" values="0%;50%;0%" dur="2s"
      repeatCount="indefinite" />
  </ellipse>
</svg>

Animace funguje pouze v Opeře a v prohlížečích s jádrem WebKit.

Se SVG dokážete udělat mnohem víc než jednoduchou vektorovou grafiku a animace. Můžete vytvořit velmi interaktivní webovou aplikaci se skriptováním, animovanými efekty, filtry a téměř čímkoli, čeho si zamanete. Pokud se chcete o SVG dozvědět víc, přečtěte si seriál SVG: Evolution, Not Revolution na webu Opery.

HTML5 Canvas

Specifikace HTML5 Canvas je v podstatě jednoduché JavaScriptové API, které umožňuje kreslit programově. Canvas sám umožňuje definovat objekt canvas (zapsaný jako element <canvas> do HTML stránky), do kterého se pak kreslí. Samotné kreslení probíhá pomocí tzv. kontextů:

První je známější a je dostupný ve všech moderních prohlížečích (v IE od verze 9), ten druhý je zatím na počátku specifikace a je zatím nemnoho experimentálních implementací.

V článku se budeme věnovat 2D kontextu, protože je široce podporovaný. Tento kontext nabízí jednoduché, ale poměrně mocné API, pomocí něhož kreslíte do 2D bitmapového „plátna“. Nemá specifikovaný „formát souboru“ a lze kreslit jen skripty. Není tu žádný DOM pro nakreslené tvary, vše je pouze v bitmapě, jako pixely. To znamená, že budete-li kreslit další a další čáry, křivky, objekty, …, nebude se nikde v paměti vytvářet stále složitější objektový model.

Zde je ukázka stejného animovaného kruhu s Canvasem:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Canvas animation example</title>
    <script type="text/javascript"><!--
window.addEventListener('load', function () {
  // Získáme canvas element.
  var canvas = document.getElementById('myCanvas'),
      w = 4,
      h = 4,
      zoompx = 6,
      step = 'zoomin';
  if (!canvas || !canvas.getContext) {
    return;
  }
  // Získáme 2d kontext.
  var ctx = canvas.getContext('2d');
  if (!ctx) {
    return;
  }
  var K = 4*((Math.SQRT2-1)/3);
setInterval(function () {
  if (step == 'zoomin') {
    w += zoompx;
    h += zoompx;
  } else if (step == 'zoomout') {
    w -= zoompx;
    h -= zoompx;
  }
  if (w > canvas.width) {
    w = canvas.width;
    step = 'zoomout';
  } else if (w < 4) {
    w = 4;
    step = 'zoomin';
  }
  if (h > canvas.height) {
    h = canvas.height;
    step = 'zoomout';
  } else if (h < 4) {
    h = 4;
    step = 'zoomin';
  }
  // Vytvoření kruhového gradientu: x0, y0, r0, x1, y1, r1.
  // Uveden je střed počátečního kruhu (x0,y0) a poloměr r0,
  // následovaný souřadnicemi (x1,y1) a poloměrem r1 vnějšího kruhu.
  var gradient = ctx.createRadialGradient(
      Math.round(w/2), Math.round(h/2), 0, Math.round(w/2), Math.round(h/2),
      Math.round(Math.min(w, h)/2));
  gradient.addColorStop(0, "#ff0");
  gradient.addColorStop(1, "#0f0");
  // nastavíme gradient pro fillStyle.
  ctx.fillStyle = gradient;
  // Poloměr a souřadnice kružnice
  var cx = w/2,
      cy = h/2,
      rx = cx*K,
      ry = cy*K;
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.setTransform(1, 0, 0, 1, Math.round((canvas.width - w) / 2),
    Math.round((canvas.height - h) / 2));
  ctx.beginPath();
  // startX, startY
  ctx.moveTo(cx, 0);
  // Řídicí body: cp1x, cp1y, cp2x, cp2y, destx, desty
  ctx.bezierCurveTo(cx + rx, 0, w, cy - ry, w, cy);
  ctx.bezierCurveTo(w, cy + ry, cx + rx, h, cx, h);
  ctx.bezierCurveTo(cx - rx, h, 0, cy + ry, 0, cy);
  ctx.bezierCurveTo(0, cy - ry, cx - rx, 0, cx, 0);
  ctx.fill();
  ctx.stroke();
  ctx.closePath();
}, 20);
}, false);
    // --></script>
  </head>
  <body>
    <p><canvas id="myCanvas" width="320" height="320">Your browser does not have
    support for Canvas.</p>
  </body>
</html>

2D kontext nemá žádné funkce pro animování – provádí jen kreslící operace, které mu zadáte a když mu je zadáte. V tomto případě je tedy kruh kreslen ve funkci, která je volána každou milisekundu.

V canvasu můžete provádět operace s jednotlivými pixely, jako jsou třeba různé obrazové filtry. Můžete vložit bitmapové obrázky jako jsou PNG a JPG či jakékoli, které umí prohlížeč zobrazit, a můžete obsah plátna exportovat či ukládat jako obrázky.

Příklad použití canvasu, který jsme si zde uvedli, není příliš vhodný pro canvas – téhož výsledku dosáhnete s mnohem menším SVG, jak jsme si ukázali výše. Navíc bude SVG čitelnější a snáze udržovatelné. Pokud chceme pomocí canvasu udělat animaci, musíme ji obsloužit pomocí časovačů, které budou vyvolávat překreslení snímek po snímku, zatímco se SVG dosáhneme téhož mnohem snáz, protože podporu animací obsahuje.

Mnohem lepší příklad použití je zobrazování dynamických informací, jako jsou interkativní grafy či analýza obrazu. Ukažme si jako příklad demo, které spočítá a zobrazí barevný histogram pomocí API pro 2D kontext:

Ukázkový kód načte obrázek do elementu img a projde všechny pixely v obrázku pomocí funkce 2D kontextu. Pixely jsou počítány pro jednotlivé kanály dle výběru barevného prostoru (RGB, HSV nebo CMYK). Když je histogram spočítán, je vykreslen do druhého canvasu.

K čemu je tedy 3D kontext? S 3D kontextem můžete kreslit trojrozměrné objekty, textury, stínování. Můžete do něj zapracovat i animace. Můžete vytvořit 3D hry a 3D modelovací nástroje. Prohlížeč takový obsah vykreslí pomocí HW akcelerace, pokud je k dispozici.

Porovnání SVG a Canvasu

Následující tabulky ukáží rozdíly mezi SVG a canvasem, jejich výhody a nevýhody.

Výhody

Canvas SVG
  • Výkonné 2D bitmapové plátno pro volné kreslení.
  • Stálý výkon – vše jsou pixely. Výkon klesá pouze s rostoucími rozměry, nikoli se složitostí obrázku.
  • Můžete výsledný obrázek uložit jako .png nebo  .jpg.
  • Skvěle se hodí pro bitmapovou grafiku (hry, fraktály apod.), editace obrázků a operace, které vyžadují přístup přímo k pixelům.
  • Nezávislý na rozlišení – SVG se proto lépe hodí pro multiplatformní uživatelská rozhraní, jelikož se přizpůsobí libovolnému rozlišení obrazovky.
  • SVG má velmi dobrou podporu pro animace. Objekty mohou být animovány přímo pomocí atributů, nebo přes JavaScript.
  • Máte plný přístup ke každému elementu přes SVG DOM API.
  • SVG je formát založený na XML, které umí prohlížeče zpracovat, takže přístupnost SVG dokumentu bude mnohem lepší než elementy canvas. Proto je SVG lepším řešením pro webová API. Navíc díky zápisu ve značkovacím jazyce lze přístupnost ještě zvýšit použitím ARIA atributů.

Nevýhody

Canvas SVG
  • Není tu žádný DOM. Vše je v pixelech.
  • Žádné API pro animace. Cokoli se má měnit, musí být naskriptováno pomocí časovačů a událostí.
  • Vykreslování textu není moc dobré.
  • Nebude pravděpodobně vhodnou volbou pro aplikace, kde je klíčová přístupnost. Canvas vám poskytuje prostor, do kterého kreslíte. Což znamená, že výsledek vaší práce jsou jen pixely – pokud tedy budoucí verze nepřinesou nějaká vylepšení přístupnosti. Prozatím můžete vložit do elementu canvas nějaký obsah, který se zobrazí v prohlížeči, pokud prohlížeč nedokáže canvas zobrazit – např. čtečka pro nevidomé. Můžete podporu canvasu detekovat i skriptem, a podle toho nabídnout alternativu pro zařízení, které nemá podporu pro  canvas.
  • Canvas není určen pro uživatelská rozhraní. Důvodem je, že UI potřebují být dynamická a reagovat na podněty od uživatele, což by s canvasem vyžadovalo manuální překreslení všech potřebných prvků. Problémem mohou být i chybějící animace a nedostatečná přístupnost.
  • Zpomalení vykreslování s nárůstem složitosti dokumentu – cokoli co používá intenzivně DOM bude pomalé.
  • SVG není vhodné pro aplikace jako jsou hry. Pravděpodobně nejlepší volbou je kombinace canvasu a SVG.

Pokud je důležité, aby aplikace byla přístupná, bude pravděpodobně vhodnější HTML než SVG, protože pro HTML existuje víc testovacích nástrojů. Na každý pád můžete přidat atributy ARIA k HTML/SVG kódu a zlepšit tak přístupnost celé aplikace.

Který formát vybrat?

Každá technologie má oblasti, v nichž je vhodné ji použít – není to tak, že byste opustili Canvas a přešli na SVG či obráceně.

Canvas použijete např. při:

  • Interaktivních úpravách obrázku: ořezy, změna velikosti, filtry (sépia, odstranění červených očí, odbarvení apod.)
  • Generování rastrové grafiky: Vizualizace dat, vykreslování fraktálů, …
  • Analýza obrázku: čtení obrazových dat pro histogramy, využití barev a další.
  • Vykreslování grafiky v hrách, jako jsou sprity či pozadí.

SVG byste měli použít v:

  • Uživatelských rozhraních webových aplikací v případech, kdy nechcete řešit rozlišení.
  • Interaktivní animovaná uživatelská rozhraní
  • Grafy a náčrtky.
  • Editování vektorových obrázků

Ve zkratce – používejte obě technologie. V hrách můžete chtít použít vykreslení rastrové grafiky pomocí canvasu, a pak animovat SVG. V aplikaci typu obrázkového editoru můžete chtít použít obojí, jak vektorovou, tak rastrovou grafiku.

Kde byste tyto technologie neměli používat? Existují čistě HTML+CSS řešení pro věci jako jsou kulaté rohy, přechody, stíny a průsvitnost. Můžete použít i knihovny jako jQuery UI. Zamyslete se, zda opravdu potřebujete SVG nebo Canvas, zda nedokážete totéž s HTML + CSS. I když je SVG převážně značkovací jazyk, budete odborníky na SVG shánět mnohem obtížněji než zkušené HTML kodéry. HTML je známější, široce podporované a má bohatší sémantické možnosti. Zvolit SVG namísto HTML + CSS čistě pro prezentační účely nebude asi nejlepší volba.

Shrnutí

V článku jsme si ukázali rozdíly mezi dvěma, na první pohled podobnými, webovými technologiemi, SVG a Canvasem. Každá technologie má své slabé i silné stránky, proto byste měli konkrétní využití dobře zvážit. Často může vhodná kombinace obou technik vést k dobrým výsledkům.

Hodně štěstí při vývoji další killer aplikace!

Další článek na téma rozdílů mezi Canvasem a HTML je např. A Bit of SVG and Canvas, jehož autorem je Divya Manian.

Tento článek je volným překladem článku SVG or Canvas? Сhoosing between the two, vydaného na Dev.Opera. Autorem původního textu je Mihai Sucan. Překlad vychází s laskavým svolením Opera Software.

Komentáře

Subscribe
Upozornit na
guest
14 Komentářů
Nejstarší
Nejnovější Most Voted
Inline Feedbacks
View all comments
Patrik Votoček

U animovaného kruhu – canvas verze je špatný link na demo správně je to http://devfiles­.myopera.com/ar­ticles/1161/cir­cle-canvas.html

Dlouhán

Koukám, že autor článku odkaz už „opravil“. Uvozovky jsem tu dal záměrně, protože ani opravený odkaz není správně.

Já osobně jsem hned po zjištění, že odkaz není funkční, zkopíroval zdroják ukázky a vyzkoušel jsem ho v prohlížečích.

bauglir

„Canvas není určen pro uživatelská rozhraní. Důvodem je, že UI potřebují být dynamická a reagovat na podněty od uživatele, což by s canvasem vyžadovalo manuální překreslení všech potřebných prvků. Problémem mohou být i chybějící animace a nedostatečná přístupnost.“
Ok, přístupnost je fakt, ale jinak je tato věta nesmysl a pravděpodobně ji psal někdo, kdo nikdy nenavrhoval nativní komponentu pod OS (minimálně windows). Protože by věděl, že k dispozici na OS má právě canvas a události a to je vše. S výjimkou pár základních controls (button, edit, apod.) Jsou všechny ostatní řešený právě přes canvas. A úplně stejný postup je vhodný i pro web, je to krásně řešitelné a svižné.
Naopak, každý, kdo někdy dělal controls pod HTML ví, co to je za peklo a s SVG si moc nepomůže.

tomaash

Obávám se, že v případě Windows je to dáno historickými důvody (WinAPI se pokud je mi známo v tomto směru zásadně nezměnilo od svého vzniku a to už bude drahně let – 20 minimalně). To za prvé.

Za druhé: moderní knihovny (ale v tomto případě je na místě spíše hovořit o frameworku) pro tvorbu uživatelského rozhraní jako je například QT4 používá intenzivně vektorovou grafiku pro standardní prvky uživatelského rozhraní.

Za třetí: nevidím nejmenší důvod proč bychom měli lpět na „ověřených“ postupech, když jsou pracnější, pomalejší a objemově náročnější.

Určitě budou situace, kdy použití canvasu a jemu blízkých postupů bude na místě, ale pro jednodušší prvky uživatelského rozhraní může být (a pravděpodobně i bude) jednodušší použít poměrně solidních možností SVG. Ale je to vždy závislé na konkrétní situaci a to je myslím to, co se autor snažil tímto článkem říci: žádná dogmata, žádné zaručené recepty, jen několik vodítek, co by asi mohlo být vhodnější a trocha vývojářské intuice :)

pas

Já naopak tipuju, že vývojářům ze světa desktopu, kteří se teď houfně přeorientují na RIA, budou HTML/SVG značky připadat jako historický balast, vhodný leda pro „lehce oživlé dokumenty“ a radši vytvoří frameworky čistě nad Canvasem. Ostatně dnes je mezi nimi tak populární Flex (framework nad Flash Playerem, což je taky takový „canvas“). Ani přístupnost by neměla být problém, který se nedá knihovnami vyřešit. Na druhou stranu je pravda, že frameworky, které umožní tvořit celou škálu aplikací (jak složité RIA, tak i ty oživlé dokumenty) jednotnými prostředky, budou taky atraktivní. Pravděpodobně nastane velká pestrost, ale rozhodně v ní bude mít místo i nějaký ten „Flex for Canvas“.

SnowmanX

No tak prr, s tim flexem … kdyz se na nej podivas, Flex nahodou ma navrh velice podobenj jako HTML + SVG (+CSS). S canvasem nema nic spolecnyho … Veci jako DOM, event bubbling, …. to ze rendering je delanej pomoci movie clipu, to je technickej detail … BTW a protoze je delanej pomoci movie clipu, je to retained mode (neco jako SVG), aby to bylo jako canvas, musel by tam bejt action script kterej by vsecko maloval (tak jako treba Swing v Jave …).

pas

No, tak to sis zrovna z mého sdělení vzal něco jiného, než jsem chtěl. :) Jasně, Flash Player není úplný ekvivalent canvasu, protože vedle low-level bitmapového API má i vlastní objektový model pro vektorové tvary (čímž je pro změnu podobný SVG), ale o to ani nejde, mohl jsem napsat Swing nebo WPF, prostě jakýkoliv framework pro UI. Stejně tak při úvahách o canvasu nemusíme mluvit o samotném canvasu, ale třeba o canvasu doplněném o WebGL…

Smyslem myšlenky je to, že bude-li canvas dostatečně výkonný, pravděpodobně kdekdo neodolá pokušení tvořit frameworky s vlastním systémem, jak deklarovat layout, jak stylovat komponenty, jak řešit data binding, atd. Nebo přenést existující frameworky, aby se využily stávající znalosti. Někdo bude brblat, že je hřích ignorovat standardizovaný markup, CSS, atd., ale snad to povede k jasnějšímu odlišování dokumentů (kde je standardizovaný markup nutností) od aplikací (kde to je fuk a konkurence může být naopak přínosnější než konsensus).

SnowmanX

Ok – to mas recht. Nakonec frameworky jako SmartGWT uz to delaji dnes …

bauglir

Je zvláštní na jednu stranu tvrdit „žádná dogmata, žádné zaručené recepty“ a na druhou se odvolávat na „moderní knihovny“ :) Ale snad k tomu „žádná dogmata, žádné zaručené recepty“ přispěje i naše diskuze :)
Fakt je ten, že má zkušenosti s tvorbou controls na canvasu (jak pod windows, tak pod browser) a tvorbou komponent pomocí HTML+JS+CSS (na SVG nesejde), i když si odpustím kategorický tón (ať si ostatně každý vybere sám), tak pro mne je jednoznačnou volbou canvas, je to mnohem, mnohem lepší (jednodužší, přehlednější, použitelnější, apod.)

v6ak

„cokoli co používá intenzivně DOM bude pomalé“ – obsahuje vedlejší větu, takže by mělo být „cokoli, co používá intenzivně DOM, bude pomalé“.

„bude pravděpodobně vhodnější HTML než SVGm“ – asi překlep („SVGm“ vs. „SVG,“)

marek

Osobne povazuji SVG za velice dobre navrzeny standard kter ma semanticky velmi dobrou citelnost. Canvas bude volba programatora, SVG bude volba zacatecnika nebo designera. V obou se da resit totez, v SVG slozitost roste, ale DOM stavajicich prohlizecu je dnes stonasobne rychlejsi nez drive a stale se zrychluje, cili performance duvody pomalicku prestavaji byt s dobou zajimavejsi a resi se prave citelnost/udri­telnost a udrzovatelnost.
Za sebe tedy plne souhlasim s puvodni filozofii clanku, ze je treba udelat analyzu problemu, jenz chceme resit a podle nej zvolit jednu, druhou nebo obe technologie kombinovat…

František Kučera

Ad „V obou se da resit totez“

To bych ani neřekl. Spor SVG vs. HTML canvas mi přijde celkem nemístný – je to jako se hádat, jestli je lepší vektorová nebo bitmapová grafika – lepší není ani jedno, záleží hlavně na předloze – fotky z foťáku asi sotva budu chtít převádět na vektory a zase různé grafy a diagramy je škoda převádět na bitmapy, protože se nedají škálovat a rozumě upravovat.

Významný rozdíl mezi SVG a canvasem vidím v tom, že canvas je čistě webová, nepřenositelná, záležitost, zatímco SVG je univerzálnější, znovupoužitelnější – nepatří jen na web, ale dá se použít i v desktopových aplikacích nebo při tisku – takže když v tom udělám nějakou vizualizaci nebo kreslení grafů, můžu tu knihovnu/kód použít i jinde než jen na nějaké HTML stránce.

afro

Tady Vám asi něco přebývá:

Interaktivní animovaná uživatelská rozhraníHighly interactive animated user interfaces.
(skoro-konec článku)
:)

Enum a statická analýza kódu

Mám jednu univerzální radu pro začínající programátorty. V učení sice neexistují rychlé zkratky, ovšem tuhle radu můžete snadno začít používat a zrychlit tak tempo učení. Tou tajemnou ingrediencí je statická analýza kódu. Ukážeme si to na příkladu enum.