Spośród wielu nowości wprowadzonych w HTML5, API do rysowania dwuwymiarowej grafiki rastrowej bez użycia wtyczek typu Flash jest z pewnością jednym z najbardziej interesujących. Wielu zresztą twierdzi (wliczając w to prominentne figury świata IT), że zwiastuje to początek końca wspomnianych pluginów. Czy rzeczywiście tak będzie, to oczywiście zobaczymy w niedalekiej przyszłości. Już teraz jednak można zobaczyć liczne przykłady na to, że technologia ta oferuje naprawdę spore możliwości.
W ramach zapoznawania się z poszczególnymi składowymi HTML5, nie mogłem więc nie przyjrzeć się bliżej elementowi <canvas>
– bo to o nim oczywiście mowa. Tradycyjnym testem dla tego rodzaju rozwiązań (tj. graficznych bibliotek 2D), który zawsze staram się zaimplementować na początku, jest… chmara odbijających się piłeczek :) Nie inaczej było i w tym przypadku, czego efekty zamieszczam tutaj wraz z krótkim opisem i wprowadzeniem w podstawy Canvasa.
Rezultat końcowy powinien być widoczny powyżej – a przynajmniej takie jest założenie :) Jeśli przykład uruchamia się poprawnie, to oprócz podziwiania trzech piłeczek, które są w nim już od razu, możemy dodawać nowe poprzez klikanie w obszar canvasa.
Robiąc to wystarczająco uparcie możemy dokonać prostej oceny efektywności renderowania w naszej przeglądarce. Wystarczy obserwować, jak zmienia się licznik FPS w miarę dodawania kolejnych obiektów. Nie obiecuję jednak, że zauważymy jakiekolwiek interesujące zmiany zanim zabawa nam się znudzi ;)
Całość przykładu od strony kodu HTML zamyka się w jednym jedynym znaczniku <canvas>
:
Pod względem zachowania wobec innych elementów strony, jest on bardzo podobny do znacznika <img>
, czyli zwykłego obrazka. Różnica polega oczywiście na tym, że można w nim swobodnie rysować. Trzeba tylko pamiętać o ustawieniu wymaganych atrybutów width
i height
na wartości w pikselach – użycie stylów CSS niestety nie wystarczy.
Narysowanie czegokolwiek wymaga już kodu przez nieco większe K, czyli JavaScriptu. Dla wygody założę, że dysponujemy biblioteką jQuery. Jeśli nie jest to prawdą, to właśnie jest doskonała okazja, żeby naprawić to niedopatrzenie ;P Biblioteka ta nie jest wprawdzie pomocna do samego rysowania po canvasie, ale znakomicie ułatwia wszystkie inne czynności, które są z tym związane.
Graficzne API elementu <canvas>
jest w całości zamknięte w obiekt kontekstu. Jest to odpowiednik kontekstu urządzenia z Windows GDI, obiektu Graphics
z GDI+ i pewnie jeszcze wielu podobnych obiektów z innych bibliotek. Wszystkie wywołania, które rysują cokolwiek albo zmieniają parametry rysowania, wykonywane są na tym właśnie obiekcie.
Kontekst pobieramy z obiektu DOM canvasa metodą getContext
:
…oczywiście po wcześniejszym sprawdzeniu, czy jest ona dostępna. Od razu też rozwieję nadzieje: niestety, obecnie "2d"
jest jedyną pewną opcją :)
update
Używając kontekstu możemy od razu coś narysować, ale jeśli nie chcemy prezentować tylko statycznych obrazków, to musimy jakoś zapewnić regularne wywoływanie kodu renderującego. Nie możemy oczywiście wpaść w pętlę, więc typowym rozwiązaniem jest funkcja setTimeout
z odpowiednio krótkim interwałem. W HTML5 istnieje jednak teoretycznie lepsze rozwiązanie w postaci funkcji requestAnimationFrame
. Ponieważ jednak z jego obsługą w różnych przeglądarkach jest różnie, trzeba sobie niestety zapewnić odpowiedni fallback:
W zamian możemy liczyć na wywołania zwrotne z częstotliwością ok. 60 na sekundę i – przynajmniej w teorii – optymalizację rysowania po elemencie DOM wskazanym jako drugi parametr.
Jak nietrudno zauważyć, piłeczki które odbijają się powyżej to po prostu wypełnione okręgi. Narysowanie takiej jakże skomplikowanej figury geometrycznej nie jest może wielkim wyzwaniem, ale wymaga zastosowania kilku koncepcji z API elementu <canvas>
.
I tak zaczynamy od ustawienia stylu wypełnienia na jednolity kolor fioletowy:
Styl ten może być nie tylko dowolnym kolorem (w formacie CSS, czyli np. #ffffff
lub rgba(...)
), ale także gradientem lub powtarzalnym wzorem złożonym z kopii obrazka. Przypomina więc to np. obiekt typu brush z GDI.
Samo rysowanie kółek jest trochę bardziej złożone niż można by się spodziewać, bo wymaga w sumie trzech wywołań:
Komu powyższy kod nie wydaje się do końca zrozumiały (przy wzięciu poprawki na język programowania, rzecz jasna ;]), polecam chociażby mój artykuł na temat pętli czasu rzeczywistego, gdzie powyższa konstrukcja jest dokładnie opisana.
Tutaj zajmiemy się natomiast wypisaniem obliczonej wartości FPS oraz aktualnej ilości piłek. Nie jest to bynajmniej trudne:
Tym razem ustawiamy styl obrysowania i wyrównywanie tekstu względem pozycji rysowania. Tekst wypisujemy funkcją strokeText
, przyjmującą też współrzędne X i Y.
To w zasadzie tyle, jeśli chodzi o samo rysowanie po canvasie. Do poprawnego działania przykład potrzebuje oczywiście jeszcze kilku innych rzeczy, takich jak choćby implementacja poruszania się i odbijania piłek oraz obsługę kliknięć. Ponieważ jednak nie dotyczą one bezpośrednio API graficznego, nie będę im poświęcał miejsca w tym i tak już zdecydowanie przydługim wpisie. Można się im oczywiście przyjrzeć, czytając pełny kod przykładu działającego wyżej.
Jeśli zaś ktoś chciałby dalszych informacji na temat możliwości i wykorzystania elementu <canvas>
, to dobrym punktem wyjścia jest tutorial na stronach Mozilli. Zawsze też można odwołać bezpośrednio do standardu :)
U mnie FPS… wzrasta razem z dodawaniem piłeczek o_o. Podskoczył z 55 do 71 po kliknięciu 100 razy.
Tak czy inaczej dzięki, wiadomo przynajmniej co będzie za 10 lat na stronach w oczy walić zamiast flasha (bo js nie jest na razie w kręgu moich zainteresowań) ;)
Bardzo przydatny artykuł. Jestem właśnie zainteresowany HTML5 ponieważ potrzebuję wykonać edytor nut, który działałby online. A ponieważ pojawił się HTML5, to porzuciłem pomysł robienia tego we flashu.
U mnie wraz z dodawaniem FPS spadaja z 50 do 22 po dodaniu 300 pileczek xD
Niezła wydajność, 1000 piłeczek redukuje FPS 2x. Szkoda że nie ma podobnej aplikacji we flash’u do porównania…
Na chrome zdaje się chodzić z dobrymi FPS-ami, ale o vsync możemy sobie pomarzyć. :D Sad.
Ciekawe, czy ten canvas doczeka się akceleracji przez OpenVG (zwłaszcza na platformach mobilnych). Wtedy by to już było COŚ.
Cóż, myślę, że sprzętowa akceleracja canvasa jest tylko i wyłącznie kwestią czasu. ;)
Przy 3142 piłeczkach mam 10 FPS. ;]
@kapec94: Miejmy nadzieję. Z GDI nie było tak różowo :)
@Zielony: Iii tam, ja przy ~12 tysiącach miałem 6-7 :)
Hmmm prezetujesz tutaj standard ktory jeszcze nie zostal wydany? Pisze wlaznie z fona, sgs2 I jakos przegladarka wyswietla mi twoj canvas. Moze chodzi o sam webkit na ktorym przegladarka jest oparta? Mimo wszystko dziala fajnie widziec nowy standard w akcji. Pozdrawiam.
Od razu jak zobaczypem to musialem sprawdzic jak to na komorce wygląda i o dziwo działa ,.trochę przycina ale i tak jestem pod wrażeniem
U mnie 300 pileczek nie zmienilo fps dalej mi sie nie chce :)