Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I control z-index of canvas objects?

When I draw some objects in canvas, sometimes new objects places under old ones. For example, I add some images to canvas and then draw a line. when I run code images are top of the line. I searched web for a solution. But there was not an straight-forward solution. :( In some cases, it have seen as a bug! in explorers. How can I control z-index?

Edit: this is my code

<img id="black_checkers_piece" src="egsdk/BlackCheckersPiece.png" style="display: none;">
<canvas id="c1" style="border:1px solid #998800"></canvas>
<script type="text/javascript">
var canvasID = document.getElementById('c1');
var ctx = canvasID.getContext('2d');
var img = new Image();
img.src = document.getElementById('black_checkers_piece').src;
img.onload = function(){
ctx.drawImage(img, 10, 10, 32, 32);
}
ctx.beginPath();
ctx.strokeStyle = 'red';
ctx.moveTo(0, 0);
ctx.lineTo(50, 50);
ctx.stroke();
</script>
like image 608
JalalJaberi Avatar asked Jan 10 '13 04:01

JalalJaberi


2 Answers

You are most likely waiting for images to load before drawing them.

Additionally, you are probably drawing lines as soon as you can.

You need to wait for all images to load, then draw everything in the order you want (from farthest z-order to closest). Do not draw anything until all images have been loaded, or your z-order will not be correct.

If you want to show items on the screen before all images are loaded, you must redraw everything on each image load, not just draw that one image.

Here's an example, where I draw 3 objects: A circle, an image, and a window. I draw them immediately, whether the image is loaded or not, but I draw all of them again once the image is loaded to ensure that the image is correctly in between the other two objects:

http://jsfiddle.net/U5bXf/32/

The shorthand relevant code (in case jsfiddle goes down) is:

var img = new Image()
img.onload = function() {
  draw()
};
img.src = "http://placekitten.com/100/140";

draw();

function draw() {
// object one

// Now we'll draw the image in between, if its loaded
ctx.drawImage(img, 100, 30);

// object two
}

Code below this line is a response to the comments

You've since posted code, but you'll notice that the only thing you are drawing in the onload function is the image.

The onload function usually happens after the other drawing commands (unless the page is already loaded, then it could be either). You need to move all drawing code into the onload function or else make your own drawing function that loads everything. For example:

<img id="black_checkers_piece" src="egsdk/BlackCheckersPiece.png" style="display: none;">
<canvas id="c1" style="border:1px solid #998800"></canvas>
<script type="text/javascript">
var canvasID = document.getElementById('c1');
var ctx = canvasID.getContext('2d');
var img = new Image();
img.src = document.getElementById('black_checkers_piece').src;
img.onload = function(){
  // assuming we want the image drawn before the line:
  ctx.drawImage(img, 10, 10, 32, 32);

  ctx.beginPath();
  ctx.strokeStyle = 'red';
  ctx.moveTo(0, 0);
  ctx.lineTo(50, 50);
  ctx.stroke();
}

like image 176
Simon Sarris Avatar answered Nov 14 '22 22:11

Simon Sarris


Canvas doesn't have any concept of 'z-index.' There are no objects in a canvas - canvases are just bitmaps, just pixels.

Are you sure you're drawing the line and the images on the canvas, and not just creating new elements (like img elements?).

If you are, then check the order in which you're calling the drawing methods like fill() and stroke(). Shapes aren't actually drawn until you do that (no matter where you have your moveTo and lineTo calls).

like image 44
hunterloftis Avatar answered Nov 14 '22 22:11

hunterloftis