NicholasByDesign NicholasByDesign - 5 months ago 9
Javascript Question

Prevent canvas element from manipulating others depending on order

I have been experimenting with canvas and things were going pretty well. However when it came time to rotate an object I had the hardest time getting it to rotate. When I finally did I found that depending on the order the objects being initiated it. The object with the rotation attributes would get passed on to objects being called after it.

All my objects were put into their own functions, and then called by a draw function. I am curious if this is always true and I have to be conscious of my objects order of initiation or if there is something I am missing.

Below if you move Obj1 and Obj2 before or after each other you will see the results are different. My goal is to have Obj1 before Obj2 and only have Obj1 rotated.



window.onload = function(){
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
x = 470,
y = 260;

canvas.width = 500;
canvas.height = 500;

function Obj1(){
ctx.beginPath();
ctx.translate(100,0);
ctx.rotate(20 * Math.PI / 180);
ctx.fillRect(x, y + 10, 20, 45);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
}

function Obj2(){
ctx.beginPath();
ctx.rect(0,300,100, 200);
ctx.fillStyle = "black";
ctx.fill();
ctx.closePath();
}


function draw(){
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
Obj1();
Obj2();
}
draw();
}

<canvas id="canvas"></canvas>




Answer

You need to reset the rotation matrix after rotating the object

Whats happening is that the transforms are cascading . Rendering happens as a stack not a per element basis .

The order of operations is

TRANSFORM 
  DRAW
RESET
DRAW

This is also a recursive process . You can say rotate the world scene / view port and also individual object .

TRANSFORM
  TRANSFORM 
    DRAW
  RESET
  TRANSFORM
    DRAW
  RESET
RESET

If you post a simple code example I can review it for you

Have a look at

https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Transformations

function Obj1(){
ctx.save();
ctx.beginPath();
ctx.translate(100,0);
ctx.rotate(20 * Math.PI / 180);
ctx.fillRect(x, y + 10, 20, 45);
ctx.fillStyle = 'blue';
ctx.fill();
ctx.closePath();
ctx.restore();
}

I believe off the top of my head .