SVG, nebo Canvas? Vyberte si

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.

Začal programovat v roce 1984 s programovatelnou kalkulačkou. Pokračoval k BASICu, assembleru Z80, Forthu, Pascalu, Céčku, dalším assemblerům, před časem v PHP a teď by rád neprogramoval a radši se věnoval starým počítačům.

Věděli jste, že nám můžete zasílat zprávičky? (Jen pro přihlášené.)

Komentáře: 14

Přehled komentářů

Vrtak-CZ Špatný link
lepsi link Re: Špatný link
Dlouhán Re: Špatný link
bauglir Canvas a UI
tomaash Re: Canvas a UI
pas Re: Canvas a UI
SnowmanX Re: Canvas a UI
pas Re: Canvas a UI
SnowmanX Re: Canvas a UI
bauglir Re: Canvas a UI
v6ak čárky
marek SVGvsCanvas
František Kučera Re: SVGvsCanvas
afro chybka
Zdroj: https://www.zdrojak.cz/?p=3334