10. Canvas czy SVG?

10. Canvas czy SVG?

Autor: Adam Stępień

Opublikowano: 8/18/2011, 12:00 AM

Liczba odsłon: 16306

Przygotowywanie grafiki zgodnie z nowym trendem i technologią HTML5 prędzej czy później stawia dylemat wyboru, czy wybierzemy wirtualne płótno Canvas czy format SVG. Nadzieje związane z Canvasem są ogromne. Powstają książki w całości jemu poświęcone. Tymczasem format SVG jest często całkowicie pomijany, a niesłusznie. Istnieją bowiem zastosowania w Sieci Web, kiedy wybranie wirtualnego płótna mija się z celem. W niniejszym artykule omówimy scenariusze, których idealnym rozwiązaniem będzie użycie SVG, a także problemy, które znakomicie adresuje Canvas. Zacznijmy od interfejsu i stworzeniu interaktywnych przycisków.

Interfejs użytkownika

Na stronach internetowych często występują przyciski, które reagują na zachowanie użytkownika, tj. najechanie elementu myszą, kliknięcie go itd. Szybkiego porównania i przeglądu dokonamy na konkretnym przykładzie: prosta strona www HTML5 z interaktywnym przyciskiem.  

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">

function rysujUI() {
    var canvas = document.getElementById("mojCanvas");
    if (canvas.getContext)
    {
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.fillStyle = "rgb(255 ,215 ,0)";
    ctx.arc(100, 100, 50, 0, 2 * Math.PI, true);
    ctx.fill();
    }
}

function klikniecieNaUI() {
alert("Kliknąłeś przycisk");
}
</script>
</head>

<body onload="rysujUI()">
<h1>Canvas UI</h1>
<canvas id="mojCanvas" width="200" height="200" onclick="klikniecieNaUI()">
</canvas>
<p>
Kliknij przycisk, aby zapisać się do listy.
</p>
</body>
</html>

Nie będziemy wyjaśniać zasady działania kodu, gdyż omawialiśmy to w innej części kursu HTML5: Canvas - podstawy. Poniżej prezentujemy kod witryny, która wykorzystuje format SVG do stworzenia grafiki.  

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function klikniecieNaUI() {
alert("Kliknąłeś przycisk.");
}
</script>
</head>
<body>
<h1>SVG UI</h1>
<svg height="200" width="200">
<circle cx="100" cy="100" r="50" fill="blue" id="mojeKolko" onclick="klikniecieNaUI();"/>
</svg>
<p>
Kliknij przycisk, aby dodać do listy.
</p>
</body>
</html>

Na pierwszy rzut oka widać różnicę w długości kodu witryny: SVG to 19 linii kodu, a Canvas 29. Przy rozbudowanych projektach różnica ta może okazać się znacząca. Uzyskanie analogicznego efektu i zaoszczędzenie mnóstwa czasu na dodatkowe linijki kodu może okazać się niebagatelnym czynnikiem przy tworzeniu interfejsu użytkownika na stronie www.

Kolejna, nie mniej ważna różnica, wiąże się z obsługą zdarzeń. Canvas obsługuje zdarzenia w kontekście całego wirtualnego płótna, zaś SVG pozwala na obsługę zdarzeń dla poszczególnych podelementów. Przygotowując nietuzinkową grafikę, może nam - jako twórcom - zależeć, aby rozróżniać kliknięcia w poszczególne obszary. W SVG zrobimy to bez problemu. Wystarczy dodać zdarzenie dla danego podelementu. W Canvasie też można rozwiązać ten problem, ale wymaga on zdecydowanie większych nakładów czasowych i więcej wysiłku. Musimy wtedy warunkować zachowanie na podstawie przechwyconych współrzędnnych kursora myszy.

Ostatnią różnicą, która może mieć duże znaczenie przy wyborze dokonywanym przez webdesignera, jest sam przebieg pisania kodu. Składnia SVG jest bardzo przyjazna, podobna do znaczników HTML-a. Natomiast Canvas wymaga złożonego procesu przygotowywania grafiki. Dla każdego elementu należy określić kolor, wypełnienie, kształt, wreszcie wypełnić ten kształt itd. Żmudny proces, o ile nie korzysta się ze "wspomagaczy".

@STRONA@

Mapy

Porównamy teraz projektowanie grafiki na potrzeby stworzenia interaktywnej mapy z użyciem Canvas i SVG. Mapa będzie reprezentowała jezioro Michigan. Kliknięcie jej obszaru spowoduje wywołanie funkcji i zmianę koloru mapy. Rozpoczniemy od wirtualnego płótna Canvas

<!DOCTYPE html>
<html>
  <head>
    <script type="text/javascript">
      var canvas;
      var ctx;
      function inicjalizacja() {
        canvas = document.getElementById("mojCanvas");
        ctx = canvas.getContext("2d");
        draw(ctx);
      }

      function draw(ctx) {
        Jezioro();
        ctx.fillStyle = "white";
        ctx.fill();
        ctx.strokeStyle = "blue";
        ctx.stroke();
      }

      function rysuj() {
        alert("To jest jezioro Michigan.");
        ctx.fillStyle = "blue";
        ctx.fill();
      }

      function Jezioro() {
        ctx.beginPath();
        ctx.moveTo(263.3, 11.3);
        ctx.lineTo(252, 28);
        ctx.lineTo(217.3, 28);
        ctx.lineTo(184, 74);
        ctx.lineTo(154, 123.3);
        ctx.lineTo(142, 170);
        ctx.lineTo(127.3, 214);
        ctx.lineTo(112.7, 252);
        ctx.lineTo(124, 284.7);
        ctx.lineTo(120, 318.7);
        ctx.lineTo(124, 356);
        ctx.lineTo(154, 389.3);
        ctx.lineTo(196.5, 356.7);
        ctx.lineTo(218.7, 318);
        ctx.lineTo(206, 240);
        ctx.lineTo(212.7, 182);
        ctx.lineTo(230.7, 121.3);
        ctx.lineTo(253.3, 103.3);
        ctx.lineTo(288, 74);
        ctx.lineTo(288, 23.3);
        ctx.closePath();
      }
    </script>
  </head>
 
  <body onload="inicjalizacja()">
    <h1>Mapy Canvas</h1>
    <canvas id="mojCanvas" width="400" height="400" onclick="rysuj()">
    </canvas>
    <p>
      Kliknij obszar mapy.
    </p>
  </body>
</html>

Teraz pora na SVG.

<!DOCTYPE HTML>
<html>
  <head>
    <script type="text/javascript">

      function rysuj() {
        alert("Lake Michigan is one of the five Great Lakes of America.");
        var mojeJezioro= document.getElementById("mojeJezioro");
        mojeJezioro.setAttribute("fill", "blue");
      }
    </script>
  </head>
 
  <body>
    <h1>Mapy SVG</h1>
    <svg x="0" y="0" width="400" height="400">
      <polygon fill="white" stroke="blue" id="mojeJezioro" onclick="rysuj()" points="263.3,11.3 252,28 217.3,28 184,74 154,123.3 142,170
      127.3,214 112.7,252 124,284.7 120,318.7 124,356 154,389.3 196.5,356.7 218.7,318 206,240 212.7,182 230.7,121.3 253.3,103.3
      288,74 288,23.3 " />
    </svg>
    <p>
      Kliknij mapę.
    </p>
  </body>
</html>

Zasadnicza różnica w obu podejścia polega na innym sposobie generowania i wyświetlania grafiki. Wybierając SVG, wszystkie szczegóły mapy zawieramy w sekcji BODY strony, a modyfikację definiuje w języku JavaScript, który zmieni atrybuty obiektu SVG. Canvas prezentuje z goła odmienne podejście. W ciele właściwym witryny definiujemy jedynie podstawowy znacznik Canvas, a wszystkie szczegóły, takie jak współrzędne ścieżki, umieszczamy jako skrypt JS. Automatycznie przekłada się to również na ilość kodu: Canvas 58 linii, a SVG 22.

@STRONA@

A zatem format SVG znakomicie sprawdza się do przygotowywania interfejsu użytkownika, do tworzenia map, a także do projektowania grafiki o wysokiej rozdzielczości, która będzie dowolnie przybliżana i oddalana. Jednakże istnieją zastosowania, gdzie najlepiej sprawdza się Canvas. Omówmy niektóre z nich.

Pierwszy przykład jest oparty na eksperymencie Adama Burmistra, który próbował przenieść technikę Ray-Traycing na grunt zastosowań webowych. Ostatecznie okazało się, że jest to prawie niemożliwe ze względu na ogromne wymagania na moc procesora. Z czasem silniki JavaScript implementowane w przeglądarkach stały się wydajniejsze. Pojawił się również Canvas, który pozwala na uzyskanie podobnego efektu bez większego wysiłku. Wirtualne płótno nadaje się znakomicie do przygotowywania różnego rodzaju filtrów graficznych i wprowadzania różnych technik obróbki grafiki piksel po pikslu.

Szybki silnik JS a Canvas

To, co jest zaletą, może stać się wadą. I tak się właśnie dzieje w przypadku uwzględniania elementów grafiki w formacie SVG w drzewie DOM. Przy skomplikowanych projektach liczba nowych pozycji może być liczona nawet w tysiącach, co nietrudno jest wygenerować np. programem Adobe Ilustrator CS5. Bardzo niekorzystnie wpływa to na wydajność i responsywność przeglądania witryny.

Dlatego też wszędzie tam, gdzie mamy jeden obiekt o dużej liczbie szczegółów, powinnyśmy wybrać rysowanie po wirtualnym płótnie. Wówczas zyskujemy czas potrzebny na aktualizację DOM. Przykładowym scenariuszem może być mapa pogody, która oprócz zwykłego konturu zawiera mnóstwo punktów i kółek o innej barwie.

Zawrotna szybkość Canvas i jego specyfika podpowiadają również wszystkim twórcom mini gier przeglądarkowych na wybranie właśnie tej techniki. W pozostałych wypadkach, takich jak zwykłe obrazy czy wykresy, zaleca się używanie SVG.

Jak wykorzystać Copilot w codziennej pracy? Kurs w przedsprzedaży
Jak wykorzystać Copilot w codziennej pracy? Kurs w przedsprzedaży

Wydarzenia