2012-02-06 89 views
28

是否可以在HTML5画布中设置绘制对象的z-index?HTML5画布集z-index

我试图让它这样一个对象可以是盈方一的“玩家”,而另一个目标是背后的“玩家”

+0

这绝对是可能的,唯一的事情是你将不得不管理自己绘制的对象数组。 – 2012-02-06 19:19:45

+0

有几个解决方案:使用多个画布元素或选择您在画布上正确绘制对象的顺序。请参阅以下问题:* [HTML5-canvas-element-multiple-in-html5-canvas](http://stackoverflow.com/questions/4422907/implementing-layers-in-html5-canvas)* [html5-canvas-element-multiple-图层](http://stackoverflow.com/questions/3008635/html5-canvas-element-multiple-layers) – styfle 2012-02-06 19:15:58

回答

36

Yes..kind肯定的。您可以使用合成来“绘制”现有像素。

ctx.globalCompositeOperation='destination-over'; 

下面是一个例子,一个演示:

var canvas=document.getElementById("canvas"); 
 
var ctx=canvas.getContext("2d"); 
 

 
var cx=100; 
 

 
drawCircle() 
 
cx+=20; 
 

 
ctx.globalCompositeOperation='destination-over'; 
 

 
$("#test").click(function(){ 
 
    drawCircle(); 
 
    cx+=20; 
 
}); 
 

 
function drawCircle(){ 
 
    ctx.beginPath(); 
 
    ctx.arc(cx,150,20,0,Math.PI*2); 
 
    ctx.closePath(); 
 
    ctx.fillStyle=randomColor(); 
 
    ctx.fill(); 
 
} 
 

 
function randomColor(){ 
 
    return('#'+Math.floor(Math.random()*16777215).toString(16)); 
 
}
body{ background-color: ivory; } 
 
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script> 
 
<button id="test">Draw new circle behind.</button><br> 
 
<canvas id="canvas" width=300 height=300></canvas>

+0

你为什么说'种'?对我来说,这看起来像是唯一真正的解决方案。 – lordvlad 2014-11-08 23:33:10

+3

我说“有点”,因为合成并不像重构图纸那样灵活地显示z分层。合成只涉及2个“层”。一层是画布上的现有像素,第二层是新绘制的像素。重构绘制正确的分层图纸会产生尽可能多的图层。 – markE 2014-11-09 03:09:47

+1

stackoverflow很棒! – Li3ro 2017-02-13 08:56:11

1

抱歉,不,canvas元素都有其Z-index和任何绘制在它上面的东西都将在该层上。

如果您在画布上指的是不同的东西,那么绘制的任何东西都会绘制在之前的任何东西之上。

3

只需先绘制它背后的东西,然后是东西,然后是其他物体。

要进行命中测试,您可能需要在显示列表上向后迭代,以测试每个对象。如果你知道物体的边界真的很好,这将起作用。

或者您可能想尝试一些标准的图形技巧,例如将每个绘制对象的独特颜色绘制到另一个内存中的画布上:点击测试,只检查内存画布上的像素颜色。整洁;-)

4

我找到的解决方案适用于我(并摆脱闪烁,欢呼!)是使用两个画布。 (或更多)

我会假定您正在制作某种游戏(因为您提到了玩家)并以此为例。

您可以从窗口的工作方式中取出一个页面,并将一个画布作为背景与另一个画布放在一起作为您的播放器画布。您可以将播放器画布标记为“脏”,或者在已更改时更改,并且只在需要时重新绘制更改的图层。这意味着您只有在玩家移动或采取行动时才更新第二张画布。

这种方法可以采取更进一步,你可以添加第三个画布的HUD游戏玩法属性,只有当玩家的统计数据发生变化时才会改变。

的HTML可能是这个样子:

<canvas id="background-canvas" height="500" width="1000" style="border:1px solid #000000;"></canvas> 
<canvas id="player-canvas" height="500" width="1000" style="border:1px solid #000000;"></canvas> 
<canvas id="hud-canvas" height="500" width="1000" style="border:1px solid #000000;"></canvas> 
2

或者你可以简单地使用的zIndex财产使用数组包含你的对象要绘制,然后排序这个数组每个孩子。然后你jist迭代该数组并绘制。

var canvas = document.querySelector('#game-canvas'); 
var ctx = canvas.getContext('2d'); 

// Define our shape "class". 
var Shape = function (x, y, z, width, height) { 
    this.x = x; 
    this.y = y; 
    this.zIndex = z; 
    this.width = width; 
    this.height = height; 
}; 
// Define the shape draw function. 
Shape.prototype.draw = function() { 
    ctx.fillStyle = 'lime'; 
    ctx.fillRect(this.x, this.y, this.width, this.height); 
}; 

// let's store the objects to be drawn. 
var objects = [ 
    new Shape(10, 10, 0, 30, 30), // should be drawn first. 
    new Shape(50, 10, 2, 30, 30), // should be drawn third. 
    new Shape(90, 10, 1, 30, 30) // should be drawn second. 
]; 

// For performance reasons, we will first map to a temp array, sort and map the temp array to the objects array. 
var map = objects.map(function (el, index) { 
    return { index : index, value : el.zIndex }; 
}); 

// Now we need to sort the array by z index. 
map.sort(function (a, b) { 
    return a - b; 
}); 

// We finaly rebuilt our sorted objects array. 
var objectsSorted = map.map(function (el) { 
    return objects[el.index]; 
}); 

// Now that objects are sorted, we can iterate to draw them. 
for (var i = 0; i < objectsSorted.length; i++) { 
    objectsSorted[i].draw(); 
} 

// Enjoy ! 

请注意,我没有测试的代码,并写在了我的手机,所以有可能是拼写错误,但应该允许明白一个道理,我希望。

+0

我认为'map.sort(function(a,b){return a - b;}); '应该是'map.sort(function(a,b){return a.value - b.value;});',我不认为你可以减去两个对象。 – dud3 2017-06-14 09:06:39