Vykreslování pomocí HTML5 a CANVAS (JavaScript)


Pro jednoduché animace můžeme použít kaskádové styly CSS3. Složité animace, grafy, hry reagující na události vyžadují již mnoho matematických a logických operací.  Pro tento účel slouží v HTML5 tag <canvas> který lze ovládat JavaScriptem.

Minimální požadavky na prohlížeč jsou: IE 10, Firefox 16, Chrome 43, Safari 10, Opera 30. Vždy je třeba počítat s tím, že na starších nebo mobilních prohlížečích nemusí být všechny funkce podporovány. Podobně mnohé blokátory reklam vypínají i JavaScript.

Velké množství vykreslování na této může zpomalit animace na pomalých počítačích. Po kliknutí do šedého okna by se měla animace vykreslit přednostně.


Příklad 01: Základní vykreslení. Po načtení okna window.onload se spustí funkce jenž vykreslí na plátno <canvas> s názvem DEMO čtyři obdélníky.


<!-- JS --------------------------------------------------------------------->

<script type="text/javascript">
 window.onload=function(){
  var DEMO = document.getElementById("DEMO");
  var DEMO = DEMO.getContext('2d');

  DEMO.fillStyle='rgb(100,200,100)';
  DEMO.fillRect(100,0,400,100); //(start_x, start_y, stop_x, stop_y)

  DEMO.fillStyle='rgb(200,150,75)';
  DEMO.fillRect(150,20,300,10); //(start_x, start_y, stop_x, stop_y)

  DEMO.fillStyle='rgb(200,75,75)';
  DEMO.fillRect(150,40,500,10); //(start_x, start_y, stop_x, stop_y)

  DEMO.fillStyle='rgb(200,0,75)';
  DEMO.fillRect(150,60,700,10); //(start_x, start_y, stop_x, stop_y)
 }
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->

<div>
 <canvas id="DEMO" width="900" height="100"></canvas>
</div>

Příklad 02: Průhlednost. Doplnění rgb o alfa kanál na rgba.


<!-- JS --------------------------------------------------------------------->

<script type="text/javascript">
 window.onload=function(){
 var DEMO = document.getElementById("DEMO");
 var DEMO = DEMO.getContext('2d');

 DEMO.fillStyle='rgba(100,200,100,1)';
 DEMO.fillRect(150,0,400,100);

 DEMO.fillStyle='rgba(200,150,75,0.5)';
 DEMO.fillRect(200,20,300,100);

 DEMO.fillStyle='rgba(200,75,75,0.5)';
 DEMO.fillRect(100,40,500,100);

 DEMO.fillStyle='rgba(200,0,75,0.5)';
 DEMO.fillRect(50,60,600,100);
 }
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<div>
 <canvas id="DEMO" width="900" height="100"></canvas>
</div>

Příklad 03: Pohyb kruhu. Pohyb kruhu ovládá jednoduchá, opakující se podmínka. Ta neustále posunuje souřadnice středu kruhu x (y a r zůstávají stejné na hodnotách 50 a 20).


<!-- JS --------------------------------------------------------------------->
<script>
//promenne a konstanty
var canvas;
var ctx;
var x = 1;
var b = 900;

//fce kruhu
function circle(x,y,r) {
 ctx.beginPath();
 ctx.arc(x, y, r, 0, Math.PI*2, true);
 ctx.fill();
}

//fce pro vymazani obsahu mezi danymi souradnicemi (obdelnik)
function reset() {
 ctx.clearRect(0, 0, 900, 200);
}

//inicializacni fce, nacte fci animate s rychlosti 10
function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(animate, 10);
}

//fce animate, zavola reset, vypocita posun, zvoli barvu a preda x pro kruh
function animate() {
 reset();

if (x < b)
 x = x + 1;
 if (x == b)
 x = 1;

ctx.fillStyle = "#FF0000";
 circle(x, 50, 20);
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 04: Pohyb kruhu ve dvou osách. Podmínka mění souřadnice vykreslení kruhu v ose x i y.


<!-- JS --------------------------------------------------------------------->
<script>

var canvas;
var ctx;
var x = 100;
var y = 50;
var width = 900;
var height = 150;

function circle(x,y,r) {
 ctx.beginPath();
 ctx.arc(x, y, r, 0, Math.PI*2, true);
 ctx.fill();
}

function reset() {
 ctx.clearRect(0, 0, 900, 200);
}

function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(animate, 10);
}

function animate() {
 reset();

if (x < width)
 x = x + 1;
 if (x >= width)
 x = 1;

if (y < height)
 y = y + 1;
 if (y >= height)
 y = 1;

ctx.fillStyle = "#FF0000";
 circle(x, y, 20);
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 05: Odraz od stěn. Rozvětvení podmínky umožní simulovat odraz od stěny. Pro lepší viditelnost je jako první vykreslen tmavý obdélník.


<!-- JS --------------------------------------------------------------------->
<script>

var canvas;
var ctx;
var x = 100;
var y = 50;
var width = 900;
var height = 150;
var directX = 1;
var directY = 1;

function circle(x,y,r) {
 ctx.beginPath();
 ctx.arc(x, y, r, 0, Math.PI*2, true);
 ctx.fill();
}

function rect() {
 ctx.fillStyle='rgb(100,100,100)';
 ctx.fillRect(0,0,900,155)
}

function reset() {
 ctx.clearRect(0, 0, 900, 200);
}

function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(animate, 5);
}

function animate() {
 reset();
 rect();

if (dirctX = 1){
 if ((x+5) < width){
 x = x + directX;
 }
 else if ((x+5) >= width){
 directX = -1;
 x = x + directX;
 }
 }

if (dirctX = -1){
 if ((x+5) > width){
 x = x + directX;
 }
 else if ((x-5) <= 0){
 directX = 1;
 x = x + directX;
 }
 }

if (dirctY = 1){
 if ((y+5) < height){
 y = y + directY;
 }
 else if ((y+5) >= height){
 directY = -1;
 y = y + directY;
 }
 }

if (dirctY = -1){
 if ((y+5) > height){
 y = y + directY;
 }
 else if ((y-5) <= 0){
 directY = 1;
 y = y + directY;
 }
 }


 ctx.fillStyle = "#FF0000";
 circle(x, y, 10);
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 06: Kreslení na plátno. Vykreslení funkce často vyžaduje zanechání stopy na plátně. Vymazat lze celé plátno nebo jen jeho část až dle potřeby. Níže se plátno vymaže po čtvrtém opakování odrazu od pravé strany.


<!-- JS --------------------------------------------------------------------->
<script>

var canvas;
var ctx;
var x = 100;
var y = 50;
var width = 895;
var height = 150;
var directX = 1;
var directY = 1;
var c = 0;

function circle(x,y,r) {
 ctx.beginPath();
 ctx.arc(x, y, r, 0, Math.PI*2, true);
 ctx.fill();
}

function reset() {
 ctx.clearRect(0, 0, 900, 155);
}

function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(animate, 2);
}

function animate() {

if (c == 4){
 reset();
 c = 0;
 }

if (dirctX = 1){
 if ((x+2) < width){
 x = x + directX;
 }
 else if ((x+2) >= width){
 directX = -1;
 c = c + 1;
 x = x + directX;
 }
 }

if (dirctX = -1){
 if ((x+2) > width){
 x = x + directX;
 }
 else if ((x-2) <= 0){
 directX = 1;
 x = x + directX;
 }
 }

if (dirctY = 1){
 if ((y+2) < height){
 y = y + directY;
 }
 else if ((y+2) >= height){
 directY = -1;
 y = y + directY;
 }
 }

if (dirctY = -1){
 if ((y+5) > height){
 y = y + directY;
 }
 else if ((y-5) <= 0){
 directY = 1;
 y = y + directY;
 }
 }


 ctx.fillStyle = "#FF0000";
 circle(x, y, 4);
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 07: Vykreslování pomocí matematické funkce sinus. 


<!-- JS --------------------------------------------------------------------->
<script>

var canvas;
var ctx;
var x = 10;
var y = 1;
var ym = 1;
var r = 2;
var width = 880;
var sinbase = 0;
var counter = 0;

function circle(x,y,r) {
 ctx.beginPath();
 ctx.arc(x, y, r, 0, Math.PI*2, true);
 ctx.fill();
}

function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(animate, 2);
}

function animate() {
 if (counter == 0){
 curve();
 }
 else if (counter == 1){
 eraser();
 }
}

function curve() {

if (x < width){
 sinbase = (x / 40);
 y = (Math.sin(sinbase) * 50) + 75;
 ym = -(Math.sin(sinbase) * 50) + 75;
 x = x + 1;
 }

 ctx.fillStyle = 'rgb(250, 100, 100)'; 
 circle(x, y - 10, r);
 ctx.fillStyle = 'rgb(250, 100, 100)';
 circle(x, y + -5, r);
 ctx.fillStyle = 'rgb(250, 0, 200)';
 circle(x, y, r);
 ctx.fillStyle = 'rgb(250, 100, 200)';
 circle(x, y + 5, r);
 ctx.fillStyle = 'rgb(250, 100, 100)';
 circle(x, y + 10, r);

 ctx.fillStyle = 'rgb(250, 100, 100)'; 
 circle(x, ym - 10, r);
 ctx.fillStyle = 'rgb(250, 100, 100)';
 circle(x, ym + -5, r);
 ctx.fillStyle = 'rgb(250, 0, 200)';
 circle(x, ym, r);
 ctx.fillStyle = 'rgb(250, 100, 200)';
 circle(x, ym + 5, r);
 ctx.fillStyle = 'rgb(250, 100, 100)';
 circle(x, ym + 10, r);

if (x >= width){
 x = 0;
 counter = 1;
 }
}

function eraser() {
 if (x >= width){
 x = 10;
 counter = 0;
 }

if (x < width){
 x = x + 1;
 ctx.clearRect(x, 0, x, 155);
 }
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 08: Vykreslování cest. Cestu mezi dvěma body lze vykreslit jako čáru nebo i křivku. Souřadnice můžeme mít uloženy v poli nebo třeba databázi či textovém souboru.


<!-- JS --------------------------------------------------------------------->
<script>

var canvas;
var ctx;
var counter1 = 0;
var counter2 = 0;
var eraserS = 0;
var eY = 0;

var ArrayXH = [050, 000, 050, 000, 025, 050, 050, 000, 000];
var ArrayYH = [000, 000, 050, 050, 075, 050, 000, 050, 000];

var ArrayXall = [410, 310, 810, 110, 610, 710, 010, 210, 510, 310];

function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(animate, 100);
}

function drawH (){
 ctx.lineTo((ArrayXH[counter1] + (ArrayXall[counter2])) , (100-ArrayYH[counter1]) );
 ctx.lineTo((ArrayXH[counter1+1] + (ArrayXall[counter2])), (100-ArrayYH[counter1+1]) );
 ctx.stroke();
}

function animate() {
 if (eraserS == 0){
 if (counter1 == 0){
 ctx.beginPath();
 }

if (counter2 < 9 ){
 if (counter1 < 8 ){
 drawH();
 counter1 = counter1 + 1;
 }

else if (counter1 >= 8 ){
 counter1 = 0;
 counter2 = counter2 + 1;
 }
 }

if (counter2 >= 9 ){
 counter1 = 0;
 counter2 = 0;
 eraserS = 1;
 ctx.endPath();
 }
 }

else if (eraserS == 1){
 eraserD();
 }
}

function eraserD() {
 if (eY < 120){
 ctx.clearRect(0, eY, 900, eY+2);
 eY = eY + 2;
 }
 else if (eY >= 120){
 eY = 0;
 counter1 = 0;
 counter2 = 0;
 eraserS = 0;
 }
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 09: Bézierovy křivky. Tyto křivky jsou úrovně n=3 (kubické) a skládají se z šesti řídících bodů.


<!-- JS --------------------------------------------------------------------->
<script>

var canvas;
var ctx;
var cAx = 10;
var cAy = 10;
var cBx = 10;
var cBya = 100;
var cByb = 200;
var cCx = 890;
var cCy = 190;
var eraserS = 0;

function init() {
 canvas = document.getElementById("canvas");
 ctx = canvas.getContext("2d");
 return setInterval(statusE, 100);
}

function bezierCDa(){
 ctx.beginPath();
 ctx.strokeStyle="black";
 ctx.bezierCurveTo(cAx, cAy, cBx, cBya, cCx, cCy);
 ctx.stroke();
}

function bezierCDb(){
 ctx.beginPath();
 ctx.strokeStyle="black";
 ctx.bezierCurveTo(cAx, cAy, cBx, cByb, cCx, cCy);
 ctx.stroke();
}

function bezierCDaD(){
 ctx.beginPath();
 ctx.strokeStyle="red";
 ctx.bezierCurveTo(cAx, cAy, cBx, cBya, cCx, cCy);
 ctx.stroke();
}

function bezierCDbD(){
 ctx.beginPath();
 ctx.strokeStyle="red";
 ctx.bezierCurveTo(cAx, cAy, cBx, cByb, cCx, cCy);
 ctx.stroke();
}

function statusE(){
 if (eraserS == 0){
 animate();
 }
 else if (eraserS == 1){
 eraserD();
 }
}


function animate() {
 bezierCDa();
 bezierCDb();

if (cBya < 200){
 cBya = cBya + 1;
 cByb = cByb - 1;
 cCx = cCx - 5;
 }

else if (cBya >= 200){
 eraserS = 1;
 }
}

function eraserD() {
 bezierCDaD();
 bezierCDbD();

if (cBya > 100){
 cBya = cBya - 2;
 cByb = cByb + 2;
 cCx = cCx + 10;
 }

else if (cBya <= 100){
 eraserS = 0;
 }
}
</script>

<!-- CSS -------------------------------------------------------------------->


<!-- HTML -------------------------------------------------------------------->
<body onload="init();">
<div>
<canvas id="canvas" width="900" height="200"></canvas>
</div>

Příklad 10: Vykreslení textu. Do plátna můžeme vykreslit i text. Nejdříve mu nastavíme vlastnosti (velikost, font, rozmazaný stín, barvy) a následně tento text vykreslíme na daných souřadnicích.


<script>
window.onload = function()
{
var canvas = document.getElementById('DEMO');
context = canvas.getContext('2d');

var text = "X-IDEA.cz";

context.font = "60px Arial";
context.shadowBlur = 2;
context.shadowColor = "rgb(120, 90, 90)";
context.fillStyle = "rgb(90, 90, 90)";
context.strokeStyle = "rgb(150, 150, 150)";
context.fillText(text, 300, 120);


context.shadowBlur = 0; 
context.fillStyle = "rgb(200, 0, 0)"; 
context.font = "20px Arial";
context.fillText("Ahoj, a dalsi text neulozeny v promenne...", 400, 170);
}
</script>

<style>
</style>

<canvas id="DEMO" width="900" height="200"></canvas>