09. Canvas - wprowadzenie do wirtualnego płótna

09. Canvas - wprowadzenie do wirtualnego płótna

Autor: Adam Stępień

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

Liczba odsłon: 19190

Na przygotowanie wirtualnego płótna Canvas i wydanie jego API czekał cały świat zorientowany wokół nowej technologii HTML5. Znacznik <canvas> - podobnie jak format SVG - pozwala na tworzenie grafiki, która jest interaktywna i korzysta z przyspieszenia sprzętowego. Instrukcje renderowania grafiki trafiają bezpośrednio do karty graficznej, dzięki czemu szybkość wyświetlania i aktualizowania grafiki jest potwornie szybka.

Canvas to uzupełnienie SVG. Nie można go traktować jako subsytut ani konkurencyjny format zapisu grafiki. Scenariusze zastosowań są diametralnie inne. Format SVG służy do projektowania grafiki wektorowej, zaś wirtualne płótno Canvas pozwala kontrolować każdy piksel obrazka. Więcej różnic i cech wspólnych, a także informacje o najlepszych zastosowań obu metod omówimy w dalszej części kursu HTML5. W niniejszym artykule omówimy podstawy wirtualnego płótna Canvas.

Wirtualne płótno Canvas pozwala na rysowanie kwadratów, prostokątów, kółek, linii, ścieżek, łuków, a nawet krzywych Beziera. Element może być animowany i interaktywny. Używając języka JavaScript można dodać reakcję na kliknięcia i ruch myszką, wpisywane znaki na klawiaturze komputerowej.

Najprostszy element Canvas stworzymy, podając tylko jego wysokość i szerokość oraz identyfikator:

<canvas id="mojCanvas" width="200" height="100"></canvas>

Jeżeli nie podalibyśmy wysokości i szerokości, przeglądarka domyślnie ustawi ich wartości na - odpowiednio - 300 piksli i 150 piksli. Domyślnym kolorem jest przezroczysta czerń.

Do elementu Canvas można się odwołać w drzewie DOM, powołując się na jego identyfikator:

<script type="text/javascript">
var canvas = document.getElementById('mojCanvas');
</script>

Korzystając z tej zmiennej, stworzymy obiekt wbudowany w HTML5, dla którego będą dostępne różne metody do rysowania.

var mojObiekt = canvas.getContext('2d');

Narysujemy teraz prostokąt i wypełnimy go kolorem pomarańczowym (w zapisie szesnastkowym #E44D26).

Prostokąt na wirtualnym płótnie

mojObiekt.fillStyle = "#E44D26";

mojObiekt.fillRect(20,10,190,75);

Pełny kod i efekt wyglądają następująco:

Prostokąt w Canvasie

<!DOCTYPE HTML>
<html>
<head>
<title>Wirtualne płótno Canvas</title>
</head>
<body>
<canvas id="mojCanvas" width="200" height="100"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("mojCanvas");
var mojObiekt = canvas.getContext('2d');
mojObiekt.fillStyle = "#E44D26";
mojObiekt.fillRect(20,10,190,75);
</script>
</body>
</html>

W metodzie fillRect jako parametr podajemy cztery liczby jako dwie współrzędne - jedna opisuje lewy górny róg prostokąta (tu: 20,10), a druga prawy dolny (190,75). Co ciekawe, początek układu współrzędnych na siatce, którą stanowi powierzchnia Canvas, rozpoczyna się w lewym górnym rogu elementu (0,0), ale im niżej, tym wartości są większe (nie maleją!).

Jeżeli chcemy narysować kwadrat, to naturalnie wykorzystujemy metody przeznaczone do rysowania prostokątów. Wówczas podajemy inne współrzędne w parametrze metody fillRect.

@STRONA@

Dowolna ścieżka na wirtualnym płótnie

Omówimy teraz rysowanie po zadanej ścieżce w Canvas. Pozwala to na narysowanie konturu praktycznie dowolnie wymyślonego obiektu. Wyobraźmy sobie artystę, który rysuje szkice ołówkiem. Jego zadanie polega w zasadzie na sekwencyjnie powtarzanych czynnościach: przesuwanie ołówka we wskazane miejsce i rysowanie do kolejnego miejsca. Podobnie Canvas realizuje rysowanie obiektu po ścieżce, udostępniając dwie metody:

  • moveTo(x,y) - przesunięcie narzędzia do rysowania we wskazany punkt (x,y)
  • lineTo(x,y) - kreślenie ścieżki bezpośrednio do punktu (x,y)
Narysujmy teraz zwykłą siatkę, czyli zbiór poziomych i pionowych linii. W tym celu skorzystamy z pętli for, która ułatwi zadanie i zredukuje powtórzenia.

Ścieżka w Canvasie

<!DOCTYPE HTML>
<html>
<head>
<title>Wirtualne płótno Canvas</title>
</head>
<body>
<canvas id="mojCanvas" width="200" height="100"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("mojCanvas");
var mojObiekt = canvas.getContext('2d');
for (var x = 0.5; x < 500; x += 10) {
mojObiekt.moveTo(x, 0);
mojObiekt.lineTo(x, 300);
}
for (var y = 0.5; y < 300; y += 10) {
mojObiekt.moveTo(0, y);
mojObiekt.lineTo(500, y);
}
mojObiekt.strokeStyle = "#eee";
mojObiekt.stroke();
</script>

Zmiennym x i y nadaliśmy wartości zmiennoprzecinkowe (0.5). Dlaczego? Ponieważ przy podaniu wartości całkowitej, grubość linii się zwiększa z jednego piksela na dwa piksle. Jest niemożliwe wyświetlić pół piksla po lewej stronie i pół piksla po prawej, stąd 2 pełne piksle.

Okrąg na wirtualnym płótnie

Canvas nie oferuje bezpośredniej metody do rysowania okręgów, ale metoda rysowania łuków pozwala uzyskać pożądany efekt. Wystarczą odpowiednie wartości parametrów, mianowicie kąt rozpoczęcia kreślenie łuku 0 i kąt zakończenia - 2 pi. Dla urozmaicenia zmienimy grubość linii okręgu oraz jej kolor.

Okrąg w Canvasie

<!DOCTYPE HTML>
<html>
<head>
<title>Wirtualne płótno Canvas</title>
</head>
<body>
<canvas id="mojCanvas" width="200" height="200"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("mojCanvas4");
var mojObiekt = canvas.getContext('2d');
var x = 100;
var y = 100;
var promien = 70;
mojObiekt.beginPath();
mojObiekt.arc(x, y, promien, 0, 2 * Math.PI, false);
mojObiekt.fillStyle = "#E44D26";
mojObiekt.fill();
mojObiekt.lineWidth = 3;
mojObiekt.strokeStyle = "#000000";
mojObiekt.stroke();
</script>
</body>
</html>

@STRONA@

Przejścia tonalne

Canvas jest zdolny także do nadawania kolorów w postaci gradientów. W tym celu wystarczy zdefiniować przynajmniej dwa miejsca zmiany koloru, a zostanie utworzone płynne przejście tonalne. Zmodyfikujemy trochę kod z poprzedniego przykładu.

Gradienty w Canvasie

<!DOCTYPE HTML>
<html>
<head>
<title>Wirtualne płótno Canvas</title>
</head>
<body>
<canvas id="mojCanvas5" width="200" height="200"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("mojCanvas5");
var mojObiekt = canvas.getContext('2d');
var x = 100;
var y = 100;
var promien = 70;
mojObiekt.beginPath();
mojObiekt.arc(x, y, promien, 0, 2 * Math.PI, false);
var mojGradient = mojObiekt.createLinearGradient(0, 100, 200, 100);
mojGradient.addColorStop(0, "#E44D26");
mojGradient.addColorStop(1, "#ffffff");
mojObiekt.fillStyle = mojGradient;
mojObiekt.fill();
mojObiekt.lineWidth = 3;
mojObiekt.strokeStyle = "#ffffff";
mojObiekt.stroke();
</script>
</body>
</html>

Canvas obsługuje dwa rodzaje przejść tonalnych:

  • Liniowe przejście tonalne
  • Promieniste przejście tonalne

My użyliśmy liniowego przejścia tonalnego. Stworzyliśmy gradient, podając linię, wzdłuż której będzie następował efekt:

var mojGradient = mojObiekt.createLinearGradient(0, 100, 200, 100);

Następnie wyznaczyliśmy tzw. miejsca stopu, określając dla nich położenie (zakres wartości 0 do 1) i kolor zapisany w systemie szesnastkowym (#E44D26 i #FFFFFF):

mojGradient.addColorStop(0, "#E44D26");
mojGradient.addColorStop(1, "#ffffff");

Na koniec powiązaliśmy wypełnienie z uprzednio zdefiniowanym przejściem tonalnym. We wcześniejszym przykładzie polu nadawaliśmy wartość koloru zapisaną heksadecymalnie.

mojObiekt.fillStyle = mojGradient;

Krzywe Beziera na wirtualnym płótnie

Ostatnią metodą, którą poznamy w tym artykule, jest rysowanie krzywych Beziera. Krzywe Bezierowskie w Canvasie

<!DOCTYPE html>
<html>
<head>
<title>Krzywe Beziera w Canvasie</title>
</head>
<body>
<canvas id="CanvasBez" width="400" height="200"></canvas>
<script type="text/javascript">
var canvas = document.getElementById("CanvasBez")
var mojObiekt = canvas.getContext('2d');
mojObiekt.beginPath();
mojObiekt.lineWidth="2";
mojObiekt.strokeStyle="black";
mojObiekt.moveTo(100,100);
mojObiekt.bezierCurveTo(200,200,200,0,300,100);
mojObiekt.stroke();
</script>
</body>
</html>

Początek krzywej ustanawiamy metodą moveTo, natomiast współrzędne końca podajemy jako ostatnie parametry metody bezierCurveTo. Punkty kontrolne natomiast podajemy na początku zestawu parametrów metody.