Podstawowe przekształcenia w elemencie Canvas

Element canvas nadaje się świetnie do tworzenia gier (oraz różnego rodzaju animacji) w środowisku przeglądarki. Nie jest bez wad ale zdecydowanie to najlepszy wybór z dostępnych opcji. API obsługujące canvas jest bardzo proste w użyciu, wystarczy wyznaczyć współrzędne x oraz y obiektu i wyrysować go stosując odpowiednie metody. Takie podejście jest idealne, jednak nie kompletne.

Manipulując tylko tymi współrzędnymi szybko natrafimy na pewne ograniczenia. Na przykład gdy chcemy obrócić element lub go przeskalować. Obliczanie nowych współrzędnych i wielkości może stać się bardzo mozolne. Na szczęście mamy przekształcenia.

JavaScript Noob Canvas Przeksztalcenia

Zalety przekształceń może nie będą oczywiste od razu, ale uwierzcie mi, warto z nich korzystać. Pewnych rzeczy wręcz nie da się zrobić bez tego narzędzia (np. obracanie obiektów o kąt), ale o tym za moment.

Stworzę stronę zawierającą element canvas, na którym z kolei narysuję prostokąt. Tak będzie wyglądał mój kod html:

Bardzo prosty dokument. Jedyne na co warto zwrócić uwagę to style, w których dodaję do mojego płótna czarną ramkę. Dzięki temu pewne przekształcenia będą bardziej widoczne.

Kolejnym krokiem jest dopisanie odpowiedniego kodu w pliku przekształcenia.js:

Tutaj również nie dzieje się jeszcze nic zaskakującego. Pobieram odniesienia do elementu canvas oraz jego kontekstu i zapisuje je w odpowiednich zmiennych. Następnie wywołuję funkcję setupCanvas, odpowiedzialną za rysowanie na płótnie. Gdyby mój program zawierał grę lub animację, ta funkcja byłaby wywoływana co klatkę.

Na początku funkcji setupCanvas, wypełniam całą przestrzeń kontekstu kolorem niebieskim. Następnie wywołuję funkcję drawRect, która wyrysuje prostokąt na płótnie. A właściwie to nie dokładnie na nim. Górny lewy róg rysowanego prostokąta znajduje się o połowę wysokości i o połowę szerokości poza płótnem. W rezultacie widoczna jest tylko ćwiartka figury.

tak wygląda początkowy stan strony.

Gdy początkowy setup mam już gotowy, czas na wprowadzenie przekształceń. W tym poście opowiem o dwóch. Wszystkie jednak obsługuje się tak samo, więc resztę można zgłębić na własną rękę. Zaznaczę jeszcze tylko, że od teraz zmieniać będzie się jedynie kod funkcji setupCanvas. Cała reszta zostaje taka sama.

Pierwsze przekształcenie jakie pokażę to translate. Tak jak inne przekształcenia jest to metoda obiektu kontekstu canvas. W wyniku wywołania translate kontekst ten zmienia się. Metoda ta przyjmuje dwa argumenty. Są to wartości o jakie przesunięty zostanie kontekst na osiach x oraz y.

Oto jak to wygląda w kodzie:

Oprócz translate, pojawiają się tu tez dwie inne nowe rzeczy, ale to za moment. Samo translate przesuwa punkt zerowy kontekstu na osiach x oraz y o wartości, które podaję w argumentach. Po wywołaniu tej metody, punkt zero zero kontekstu znajduje się na środku płótna.

Wywołanie fillRect, które wcześniej powodowało wypełnienie elementu canvas niebieskim kolorem, teraz pokaże tylko ćwiartkę kwadratu. Za to prostokąt wywołany przez drawRect będzie teraz widoczny cały, ponieważ jego środek znajdować będzie się dokładnie na środku płótna.

tak wygląda strona po wprowadzeniu przekształcenia translate.

Wszystko się zgadza. Tym razem na płótnie jest jednak jeszcze jeden prostokąt, w takiej samej pozycji jak w pierwszym przykładzie. To dlatego, że na końcu setupCanvas wywołuję drawRect jeszcze raz (przypominam, to dokładnie ta sama funkcja, parametry się nie zmieniają, prostokąt przemieszcza się z powodu przekształceń). Jednak w poprzedniej linijce znajduje się wywołanie metody kontekstu restore. Metoda ta sprawia, że kontekst płótna wraca do stanu, jaki miał miejsce podczas najbliższego wywołania metody save. W moim wypadku jest to na samym początku metody, czyli przed przekształceniem. Idealnie.

Wywołania save oraz restore, występują bardzo często (a praktycznie zawsze) w połączeniu z przekształceniami. Zazwyczaj jednak w metodach rysujących poszczególne obiekty. Za chwilę wyjaśnię dokładniej dlaczego tak jest.

Kolej na kolejne przekształcenie, według mnie jedno z najprzydatniejszych. Chodzi o rotate, w wyniku którego, płótno obraca się o kąt podany jako argument.

Tak wygląda funkcja setupCanvas po dodaniu przekształcenia rotate:

Wszystko zostaje tak jak w poprzednim przykładzie, jedyna różnica jest taka, że po przesunięciu kontekstu płótna wywołuję rotate, w wyniku którego płótno się obraca. Warto zwrócić uwagę, że ponieważ pomiędzy nimi nie użyłem restore, efekty obu przekształceń będą widoczne.

rotate, powoduje, że płótno obraca się zgodnie ze wskazówkami zegara o kąt podany w argumencie. Trzeba jednak pamiętać, że wszelkie wartości kątów, podawane są w radianach a nie w zwykłych stopniach. Nie będę dokładnie tłumaczył jak to działa, jeżeli nie wiesz jak działają radiany, musisz koniecznie się dowiedzieć, to niezbędna wiedza 😉 Na tę chwilę warto wiedzieć tylko, że PI radianów to 180 stopni. Jeżeli więc podzielę PI na cztery dostane 45 stopni. I dokładnie o tyle obracam swój kontekst (który jest już przesunięty na środek płótna). Następnie rysuję co trzeba i resetuję kontekst za pomocą restore. Ostatnim krokiem jest kolejne wywołanie drawRect.

Tak wygląda płótno po wprowadzeniu powyższych przekształceń.

I to wygląda bardzo fajnie. Ciężko jest osiągnąć taki efekt bez przekształceń.

Wspominałem wcześniej, że wraz z przekształceniami, często używa się metod save i restore. Dzięki temu można przekształcać tylko wybrane obiekty a nie całe płótno. W grze, na przykład, chciałbym aby jakiś element się obracał, ale nie chciałbym aby cała gra obracała się razem z nim. W takim wypadku trzeba użyć save przed narysowaniem obiektu, użyć rotate, narysować obiekt po czym wywołać restore i rysować resztę obiektów.

Na koniec pokażę jeszcze jeden przykład, tym razem chcę aby duży niebieski kwadrat przesunął się i obrócił, ale czerwony prostokąt ma zostać tylko przesunięty:

Tak jak mówiłem, używam save i restore dla każdego obiektu. Drugi prostokąt rysuje na końcu, w oryginalnym, nie zmienionym kontekście, więc nie potrzebuję dodatkowych metod.

Oto wynik.

Na dziś to wszystko. Jeśli chcesz być na bieżąco z postami na blogu zachęcam do polubienia mojej strony na facebooku. Zawsze zamieszczam tam informacje o wszystkich nowościach. Jest to też dobre miejsce na kontakt ze mną. Na wszystkie pytania zawsze odpowiem :).

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *