Canvas, rysowanie na podstawie danych

Aplikacje Internetowe: Kurs › Canvas, rysowanie na podstawie danych

Treść zadania

Mamy taką zawartośc strony:

<!DOCTYPE html>
<html>
<head>
<title>Rysowanie</title>
<script>
domek = {"Paths" : [
[
{"Type" : "Rectangle", "X" : 100, "Y" : 100, "Width": 100, "Height": 100},
{"Type" : "Move", "X" : 100, "Y" : 100},
{"Type" : "LineTo", "X" : 150, "Y" : 0},
{"Type" : "LineTo", "X" : 200, "Y" : 100}
],[
{"Type" : "Rectangle", "X" : 120, "Y" : 120, "Width": 20, "Height": 20}
],[
{"Type" : "Rectangle", "X" : 160, "Y" : 120, "Width": 20, "Height": 20}
],[
{"Type" : "Rectangle", "X" : 140, "Y" : 150, "Width": 20, "Height": 50}
]
]} </script>
<script>
function rysujdomek() {
}
</script> </head>
<body>
<button id="rysuj" onclick="rysujdomek()">Rysuj domek</button>
<canvas id="canvas" width="400" height="300">Twoja przeglądarka nie obsługuje canvas</canvas>
</body>
</html>

Zadanie:
Nalezy tak napisac treśc funkcji rysujdomek() aby powstał domek opisany przez zmienną domek:

Wskazówki

  • każda ścieżka jest tablica obiektów do narysowania w ramach sciezki
  • każdy obiekt wchodzący w skład ścieżki ma własciwośc Type która okresla rodzaj rysowanego obiektu
    Rectange,Move,LineTo
  • nalezy narysować wszystkie scieżki na obiekcie canvas id=canvas
  • wskazówka
    domek.Paths.length; //ilośc sciezek do narysowania
    var obiekty = domek.Paths[0] //odczyt pierwszej sciezki do narysowania
    obiekty.length; //ilosc obiektów do narysowania w ramach sciezki
    obiekty[0].Type; //odczyt typu pierwszego obiektu w ramach sciezki
    obiekty[0].X; //odczyt właściwoaści X

 

Rozwiązanie 

popatrzmy najpierw na zawartosc pliku domek.js i zdefiniowaną tam zmienną domek

domek = {Paths: [....]};

klamry { i } oznaczają ze mamy do czynienia z obiektem, jego jedyną właściwością jest Paths:

domek.Paths

teraz popatrzmy jaką partośc ma Paths

Paths: [....];

klamry [ i ] wskazują ze mamy do czynienia z tablicą przypatrzmy się jak wyglądają kolejne elementy tablicy:

Paths: [[...],[...],[...],[...]];

każdy z elementów tablicy jest określony przez klamry [ i ] co oznacza że każdy element tablicy jest tablicą (strukturę taką zwykle nazywa się tablicą tablic)) odczytajmy pierwszy element tablicy Paths (pamiętajmy że Paths jest właściwością obiektu domek):

var obiekty = domek.Paths[0];

przypatrzmy się teraz co jest zawartością zmiennej obiekty:

obiekty = [{...},{...},{...}]

każdy element tablicy obiekty jest określony przez klamry { i } co zonacza ze jest obiektem (podobnie jak zmienna domek) odczytajmy pierwszy element tablicy obiekty (czyli ten o indeksie 0):

var obiekt = obiekty[0];

sprawdzmy co jest w zmiennej obiekt:

    
	obiekt = {
	   "Type" : "Rectangle",
	   "X" : 100,
	   "Y" : 100,
	   "Width": 100,
	   "Height": 100
	}

(cudzysłowy w nazwach właściwości są nieobowiązkowe w tym przypadku, odczytuje się je identycznie jakby codzysłowów nie było) mamy tu obiekt mający właściwości: Type, X, Y, Width, Height naszym zadaniem jest narywanie na canvasie figury opisanej przez parametr Type oraz poprzez pozostałe parametry, w przypadku Rectange będą to X, Y, Width i Height, więc kod w powyższym przypadku powinien być taki:

ctx.rect(obiekt.X,obiekt.Y,obiekt.Width,obiekt.Height);

w przypadku przesuniecia to będzie

ctx.moveTo(obiekt.X,obiekt.Y);

a w przypadku lini

ctx.lineTo(obiekt.X,obiekt.Y);

podsumowując ten fragment kod rysujący uwzględniający odczyt właściwości Type będzie wyglądał tak:

    switch (obiekt.Type) {
	  case "Rectangle": ctx.rect(obiekt.X,obiekt.Y,obiekt.Width,obiekt.Height);break;
	  case "Move": ctx.moveTo(obiekt.X,obiekt.Y);break;
	  case "LineTo": ctx.lineTo(obiekt.X,obiekt.Y);break;
	}

będziemy musieli powtórzyć ten kod dla każdego obiektu na ścieżce, a więc tworzymy pętlę odczytująca każdy obiekt ścieżki:

    for (var i=0;i<obiekty.length;i++) {
	   var obiekt = obiekty[i];
	   switch (obiekt.Type) {
	      ...
	   }
	}

ok, ale to dopiero pierwsza scieżka, jak widać nasz ryzunek składa się z większej ilości ścieżek, ponieważ również są one tablicą możemy je po kolei odczytywać w pętli

    for (var j=0;j<domek.Paths.length;j++) {
	   var obiekty = domek.Paths[j];
	   .... //tutaj kod powyżej rysujący obiekty ścieżki
    }

proszę zauważyć ze celowo użyłem innej zmiennej pętli (wcześniej i do obiektów, teraz j dla ścieżek), chodzi o to aby wartości zmiennych się nie pomieszały należy również pamięteać ze aby narysować coś na canvasie trzeba rozpocząć scieżekę przez beginPath() i ją narysować poprzez stroke(), dopiszmy więc w odpowiednich miejscach

   for (var j=0;j<domek.Paths.length;j++) {
	   var obiekty = domek.Paths[j];
	   ctx.beginPath();
	   .... //tutaj kod powyżej rysujący obiekty ścieżki
	   ctx.stroke();
    }

no to jeszcze trzeba w znany sposób "pobrac" canvas z interfejsu:

var canvas = document.getElementById("canvas");

oraz utworzyć kontekst rysowania:

var ctx = canvas.getContext("2d");

i można skompletowac kod:

Kompletne rozwiązanie

    
	function rysujdomek() {
	   var canvas = document.getElementById("canvas");
	   var ctx = canvas.getContext("2d");
	    //pętla dla ścieżek
		for (var j=0;j<domek.Paths.length;j++) {
		   var obiekty = domek.Paths[j];
		   ctx.beginPath();
		   //pętla dla obiektów
			for (var i=0;i<obiekty.length;i++) {
			   var obiekt = obiekty[i];
				switch (obiekt.Type) {
				  case "Rectangle": ctx.rect(obiekt.X,obiekt.Y,obiekt.Width,obiekt.Height);break;
				  case "Move": ctx.moveTo(obiekt.X,obiekt.Y);break;
				  case "LineTo": ctx.lineTo(obiekt.X,obiekt.Y);break;
				}
			}
		   ctx.stroke();
		}
	}

Komentarze

Komentarze do Canvas, rysowanie na podstawie danych na it.jursza.com