Javascript HTML5画布集z索引

Javascript HTML5画布集z索引,javascript,html,Javascript,Html,可以在HTML5画布中设置绘制对象的z索引吗 我正在尝试获取它,以便一个对象可以位于“玩家”前面,另一个对象位于“玩家”后面。对不起,不,画布元素将有其z索引,在其上绘制的任何内容都将位于该层上 如果你在画布上指的是不同的东西,那么是的,所画的任何东西都是在之前画过的东西之上。只需先画它后面的东西,然后是东西,然后是其他对象 要进行命中测试,您可能需要向后迭代显示列表,测试每个对象。如果您非常了解对象边界,这将起作用 或者,您可能想尝试一些标准的图形技巧,例如,将相同的对象绘制到另一个内存画布上

可以在HTML5画布中设置绘制对象的z索引吗


我正在尝试获取它,以便一个对象可以位于“玩家”前面,另一个对象位于“玩家”后面。对不起,不,画布元素将有其z索引,在其上绘制的任何内容都将位于该层上


如果你在画布上指的是不同的东西,那么是的,所画的任何东西都是在之前画过的东西之上。

只需先画它后面的东西,然后是东西,然后是其他对象

要进行命中测试,您可能需要向后迭代显示列表,测试每个对象。如果您非常了解对象边界,这将起作用


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

我找到了一个适合我的解决方案(而且摆脱了闪烁,万岁!)就是使用两张画布。(或以上)

我将假设您正在制作某种类型的游戏(因为您提到了一名玩家),并以此为例

您可以从windows的工作方式中选取一个页面,首先将一个画布作为背景,然后将另一个画布放在其上作为您的播放器画布。您可以将播放器画布标记为“脏”或在任何时候更改,并且仅在需要时重新绘制更改的层。这意味着您仅在玩家移动或采取行动时更新第二个画布

这种方法可以走得更远,你可以为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>

是……有点是。您可以使用合成来“向后绘制”现有像素。

ctx.globalCompositeOperation='destination-over';
下面是一个示例和演示:

var canvas=document.getElementById(“canvas”);
var ctx=canvas.getContext(“2d”);
var-cx=100;
画圈()
cx+=20;
ctx.globalCompositeOperation='destination-over';
$(“#测试”)。单击(函数(){
画圈();
cx+=20;
});
函数drawCircle(){
ctx.beginPath();
ctx.arc(cx,150,20,0,数学PI*2);
ctx.closePath();
ctx.fillStyle=randomColor();
ctx.fill();
}
函数randomColor(){
return(“#”+Math.floor(Math.random()*16777215.toString(16));
}
body{背景色:象牙;}
画布{边框:1px纯红;}

在后面画一个新圆圈。

或者,您可以简单地使用包含要绘制的对象的数组,然后使用每个子对象的
zIndex
属性对该数组进行排序。然后迭代该数组并绘制

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.value - b.value;
});

// 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 !
var canvas=document.querySelector(“#游戏画布”);
var ctx=canvas.getContext('2d');
//定义我们的形状“类”。
变量形状=函数(x、y、z、宽度、高度){
这个.x=x;
这个。y=y;
这个.zIndex=z;
这个。宽度=宽度;
高度=高度;
};
//定义形状绘制功能。
Shape.prototype.draw=函数(){
ctx.fillStyle='石灰';
ctx.fillRect(this.x,this.y,this.width,this.height);
};
//让我们存储要绘制的对象。
变量对象=[
新形状(10,10,0,30,30),//应首先绘制。
新的形状(50,10,2,30,30),//应该画第三个。
新形状(90,10,1,30,30)//应在第二个位置绘制。
];
//出于性能原因,我们将首先映射到临时数组,对临时数组进行排序并映射到对象数组。
var map=objects.map(函数(el,索引){
返回{index:index,value:el.zIndex};
});
//现在我们需要按z索引对数组进行排序。
map.sort(函数(a,b){
返回a.value-b.value;
});
//我们最终重建了排序对象数组。
var objectsSorted=map.map(函数(el){
返回对象[el.index];
});
//现在,对象已排序,我们可以迭代绘制它们。
对于(var i=0;i

请注意,我没有测试该代码并将其写在手机上,因此可能会有打字错误,但我希望这能让我理解其原理。

有两种解决方案:使用多个画布元素或选择正确在画布上绘制对象的顺序。请看以下问题:*这是绝对可能的,唯一的问题是您必须自己管理要绘制的对象数组。为什么要说“种类”?对我来说,这似乎是唯一真正的解决方案。我说“有点”,因为合成并不像重构图形那样灵活,首先要正确地显示z层。合成只涉及2个“层”。一层是画布上的现有像素,第二层是新绘制的像素。重构以绘制正确分层的图形,可以生成所需的任意多个图层。stackoverflow很棒!喜欢使用
toString(16)
-你教了我一个新技巧:)@conor909它将数字转换为十六进制格式,然后作为字符串返回,因此基本上它允许你轻松地将数字rgb值转换为十六进制字符串等价物。尝试在控制台中运行上面显示的randomColor()函数,以在Action中查看它,我认为
map.sort(函数(a,b){returna-b;})
应该是
map.sort(函数(a,b){返回a.value-b.value;}),我认为不能只减去两个对象。