Javascript 如何控制画布对象的 z-index?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14250697/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 16:10:30  来源:igfitidea点击:

How can I control z-index of canvas objects?

javascripthtmlcanvas

提问by JalalJaberi

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?

当我在画布上绘制一些对象时,有时新对象会放在旧对象下。例如,我将一些图像添加到画布,然后画一条线。当我运行代码图像是最重要的。我在网上搜索了解决方案。但是没有一个直接的解决方案。:( 在某些情况下,它被视为一个错误!在资源管理器中。如何控制 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>

回答by Simon Sarris

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, thendraw everything in the order you want (from farthest z-order to closest). Do not draw anythinguntil all images have been loaded, or your z-order will not be correct.

您需要等待所有图像加载完毕,然后按照您想要的顺序(从最远的 z 顺序到最近的顺序)绘制所有内容。在加载所有图像之前不要绘制任何内容,否则您的 z-order 将不正确。

If you want to show items on the screen before all images are loaded, you must redraw everythingon 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 allof them again once the image is loaded to ensure that the image is correctly in between the other two objects:

这是一个示例,我在其中绘制了 3 个对象:一个圆、一个图像和一个窗口。无论图像是否加载,我都会立即绘制它们,但是一旦图像加载,我会再次绘制所有它们以确保图像正确位于其他两个对象之间:

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

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

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

速记相关代码(以防 jsfiddle 出现故障)是:

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 onloadfunction is the image.

您已经发布了代码,但您会注意到您在onload函数中绘制的唯一内容是图像。

The onload function usually happens afterthe 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:

onload 函数通常发生其他绘图命令之后(除非页面已经加载,否则它可能是)。您需要将所有绘图代码移动到 onload 函数中,或者制作自己的绘图函数来加载所有内容。例如:

<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();
}

回答by hunterloftis

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

Canvas 没有任何“z-index”的概念。画布中没有对象 - 画布只是位图,只是像素。

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

您确定要在画布上绘制线条和图像,而不仅仅是创建新元素(例如 img 元素?)。

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).

如果是,请检查调用fill() 和stroke() 等绘图方法的顺序。在您这样做之前,实际上不会绘制形状(无论您在何处进行 moveTo 和 lineTo 调用)。

回答by mvprzy

I have been using fabric.js and it has some features that you may find useful. While not z-index per se, it can set a background or an overlay - below is an example found on http://fabricjs.com/customization/

我一直在使用fabric.js,它有一些你可能会觉得有用的功能。虽然不是 z-index 本身,但它可以设置背景或叠加层 - 以下是http://fabricjs.com/customization/上的示例

var canvas = new fabric.Canvas('c13'); canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 })); canvas.setOverlayImage('../assets/jail_cell_bars.png', canvas.renderAll.bind(canvas)); this.__canvases.push(canvas);

var canvas = new fabric.Canvas('c13'); canvas.add(new fabric.Circle({ radius: 30, fill: '#f55', top: 100, left: 100 })); canvas.setOverlayImage('../assets/jail_cell_bars.png', canvas.renderAll.bind(canvas)); this.__canvases.push(canvas);