Načrtovanje in razvoj spletnih aplikacij

Canvas: risalna orodja, efekti in transformacije

Element <canvas> omogoča risanje različnih grafičnih vsebin z uporabo jezika JavaScript. Na platno lahko rišemo osnovne geometrijske oblike, poti, besedilo, slike, sence, barvne prelive in posamezne slikovne pike. Tak način je uporaben pri interaktivnih prikazih, grafih, animacijah in drugih dinamičnih vsebinah.

Na tej strani so prikazani zahtevnejši primeri risanja na platno. Primeri so razdeljeni po vsebinskih sklopih, da je razvidna razlika med osnovnimi oblikami, risanjem poti, izpisom besedila, uporabo slik, senc, prelivov in neposredno obdelavo slikovnih pik.

Pomni: Pri vseh primerih moramo najprej poiskati element <canvas> in pridobiti njegov 2D-kontekst. Šele nato lahko nastavljamo lastnosti risanja in uporabljamo metode za izris.

Osnovne črte in oblike

Z lastnostma fillStyle in strokeStyle določimo barvo polnila oziroma obrisa. Z metodama fillRect(x, y, width, height) in strokeRect(x, y, width, height) rišemo polnjene ali obrisane pravokotnike. Z metodo clearRect(x, y, width, height) lahko del platna izbrišemo.

V spodnjem primeru je najprej narisan zunanji okvir platna, nato moder polnjen pravokotnik, obrisan pravokotnik in na koncu še izbrisano osrednje območje, ki ga ponovno poudari obris.

<canvas id="example1" width="200" height="200">
   Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
   var example1 = document.getElementById('example1');
   var context = example1.getContext('2d');

   context.strokeStyle = "gray";
   context.lineWidth = 1;
   context.strokeRect(0, 0, 200, 200);

   context.fillStyle = "blue";
   context.strokeStyle = "darkorange";
   context.lineWidth = 5;
   context.fillRect(10, 10, 150, 50);
   context.strokeRect(10, 72, 150, 50);
   context.clearRect(40, 30, 90, 60);
   context.strokeRect(40, 30, 90, 60);
</script>
Vaš brskalnik ne podpira elementa canvas.

Pozor: Metoda clearRect() ne nariše nove oblike, ampak odstrani že narisano vsebino z izbranega dela platna.

Poti in krivulje

Pri risanju poti navadno uporabimo metode beginPath(), moveTo(), lineTo(), nato pa pot izrišemo z fill() ali stroke(). Po potrebi jo zaključimo z metodo closePath(). Tak način uporabljamo pri risanju trikotnikov, mnogokotnikov, lomljenih črt in drugih zahtevnejših oblik.

V prikazanem primeru iz treh točk nastane zaprta pot v obliki trikotnika, ki je nato zapolnjena in obrisana.

<canvas id="example2" width="400" height="300">
   Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
   var example2 = document.getElementById('example2');
   var context = example2.getContext('2d');

   context.strokeStyle = "gray";
   context.lineWidth = 1;
   context.strokeRect(0, 0, 400, 300);

   context.beginPath();
   context.lineWidth = 3;
   context.strokeStyle = "#000000";
   context.fillStyle = "blue";
   context.moveTo(100, 50);
   context.lineTo(10, 200);
   context.lineTo(200, 200);
   context.closePath();
   context.fill();
   context.stroke();
</script>
Vaš brskalnik ne podpira elementa canvas.

Besedilo

Na platno lahko izrišemo tudi besedilo. Za to uporabimo metodi fillText() in strokeText(). Lastnosti font, textAlign in textBaseline določajo videz, poravnavo in navpično lego besedila.

V spodnjem primeru je prvo besedilo zapolnjeno, drugo pa izpisano samo z obrisom.

<canvas id="example3" width="400" height="200">
   Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
   var example3 = document.getElementById('example3');
   var context = example3.getContext('2d');

   context.strokeStyle = "gray";
   context.lineWidth = 1;
   context.strokeRect(0, 0, 400, 200);

   context.fillStyle = "blue";
   context.font = "italic 40px sans-serif";
   context.textBaseline = "top";
   context.fillText("HTML5 je super!", 0, 0);

   context.font = "bold 40px sans-serif";
   context.strokeText("Canvas je uporaben!", 0, 60);
</script>
Vaš brskalnik ne podpira elementa canvas.

Slike

Na platno lahko prenesemo tudi obstoječo sliko. Za to uporabimo metodo drawImage(). Sliko lahko narišemo v izvirni velikosti, pomanjšano, povečano ali pa izrežemo le del slike in ga prikažemo drugje na platnu.

Primer slike:
Slovenija

V naslednjem primeru je ista slika prikazana na tri načine: v izvirni velikosti, pomanjšana in delno izrezana.

<canvas id="example6" width="350" height="250">
Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
var example6 = document.getElementById('example6');
var context = example6.getContext('2d');
var slika = document.getElementById('slovenija');

function narisiSliko() {
	context.clearRect(0, 0, 350, 250);
	context.strokeStyle = "gray";
	context.lineWidth = 1;
	context.strokeRect(0, 0, 350, 250);

	context.drawImage(slika, 25, 25);
	context.drawImage(slika, 3, 3, 150, 105);
	context.drawImage(slika, 50, 50, 100, 100, 245, 140, 100, 100);
}

if (slika.complete) {
	narisiSliko();
} else {
	slika.onload = narisiSliko;
}
</script>
Vaš brskalnik ne podpira elementa canvas.

Pozor: Če slika še ni naložena, je ni mogoče pravilno izrisati na platno. Zato je pri delu s slikami smiselno preveriti, ali je slika že na voljo, oziroma uporabiti dogodek onload.

Senčenje

Za senčenje uporabljamo lastnosti shadowColor, shadowBlur, shadowOffsetX in shadowOffsetY. Te lastnosti določajo barvo sence, njeno mehkobo in odmik v vodoravni ter navpični smeri.

<canvas id="example4" width="300" height="200">
   Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
   var example4 = document.getElementById('example4');
   var context = example4.getContext('2d');

   context.strokeStyle = "gray";
   context.lineWidth = 1;
   context.strokeRect(0, 0, 300, 200);

   context.shadowOffsetX = 10;
   context.shadowOffsetY = 10;
   context.shadowBlur = 15;
   context.shadowColor = 'rgba(50, 50, 10, 0.5)';
   context.fillStyle = 'blue';
   context.fillRect(20, 20, 150, 100);
</script>
Vaš brskalnik ne podpira elementa canvas.

Barvni prelivi

Za prelive najpogosteje uporabimo metodi createLinearGradient() in createRadialGradient(), nato pa z metodo addColorStop() določimo posamezne barve in njihove prehode. Linearni preliv poteka po ravni črti, radialni preliv pa krožno od središča navzven.

<canvas id="example5" width="350" height="150" style="border:1px solid #d3d3d3;">
   Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
   var c = document.getElementById("example5");
   var ctx = c.getContext("2d");

   var grdLin = ctx.createLinearGradient(0, 0, 200, 0);
   grdLin.addColorStop(0, "white");
   grdLin.addColorStop(1, "red");
   ctx.fillStyle = grdLin;
   ctx.fillRect(10, 10, 150, 80);

   var grdRad = ctx.createRadialGradient(255, 50, 5, 255, 60, 100);
   grdRad.addColorStop(0, "blue");
   grdRad.addColorStop(1, "white");
   ctx.fillStyle = grdRad;
   ctx.fillRect(180, 10, 150, 80);
</script>
Vaš brskalnik ne podpira elementa canvas.

Slikovne pike

Z metodama createImageData() in putImageData() lahko ustvarjamo in izrisujemo slikovne pike. Vsaka slikovna pika vsebuje štiri vrednosti: rdečo, zeleno, modro in alfa kanal. Tak način omogoča zelo natančno obdelavo grafične vsebine na ravni posameznih točk.

V spodnjem primeru sta ustvarjeni dve rdeči področji z različno stopnjo prosojnosti. Barva je nastavljena prek vrednosti za rdeči kanal, prosojnost pa prek alfa kanala.

<canvas id="example7" width="350" height="150" style="border:1px solid #d3d3d3;">
   Vaš brskalnik ne podpira elementa canvas.
</canvas>

<script>
   var cnv = document.getElementById('example7');
   var context = cnv.getContext('2d');

   var imgd1 = context.createImageData(100, 100);
   var pix1 = imgd1.data;

   for (var i = 0; i < pix1.length; i += 4) {
     pix1[i] = 255;
     pix1[i + 3] = 80;
   }

   context.putImageData(imgd1, 10, 10);

   var imgd2 = context.createImageData(100, 100);
   var pix2 = imgd2.data;

   for (var j = 0; j < pix2.length; j += 4) {
     pix2[j] = 255;
     pix2[j + 3] = 200;
   }

   context.putImageData(imgd2, 150, 10);
</script>
Vaš brskalnik ne podpira elementa canvas.

Priporočila

  • Vsakemu elementu <canvas> določimo enoličen atribut id.
  • Pri več primerih je priporočljivo uporabiti ločene spremenljivke za posamezna platna in njihove kontekste.
  • Pri delu s slikami preverimo, ali je slika že naložena.
  • Risanje je smiselno razdeliti v manjše funkcije, kadar je primer obsežnejši.

Na strani s primeri je dobro, da ima vsak element <canvas> svoj enoličen id, prav tako pa naj ima vsaka skripta svojo spremenljivko za kontekst.