HTML5 Canvas 设置 z-index
Posted
技术标签:
【中文标题】HTML5 Canvas 设置 z-index【英文标题】:HTML5 Canvas set z-index 【发布时间】:2012-02-28 06:16:54 【问题描述】:是否可以在 html5 画布中设置绘制对象的 z-index?
我正在尝试获取它,以便一个对象可以在“玩家”之前,而另一个对象可以在“玩家”之后
【问题讨论】:
有几种解决方案:使用多个画布元素或选择正确在画布上绘制对象的顺序。请参阅以下问题:* implementing-layers-in-html5-canvas * html5-canvas-element-multiple-layers 这绝对是可能的,唯一的事情是你必须自己管理要绘制的对象数组。 【参考方案1】:抱歉,不,canvas 元素将有它的 z-index 并且在其上绘制的任何内容都将在该层上。
如果您指的是画布上的不同事物,那么是的,任何被绘制的东西都会被绘制在之前的任何东西之上。
【讨论】:
【参考方案2】:只需先画它后面的东西,然后是东西,然后是其他对象。
要进行命中测试,您可能需要在显示列表上向后迭代,测试每个对象。如果您非常了解对象边界,这将起作用。
或者您可能想尝试一些标准的图形技巧,例如将相同的对象绘制到另一个内存画布上,并为每个绘制的对象使用独特的颜色:要进行测试,只需检查内存画布上的像素颜色。整洁;-)
【讨论】:
【参考方案3】:我发现一个对我有用的解决方案(并且摆脱了闪烁,欢呼!)是使用两个画布。 (或更多)
我假设您正在制作某种游戏(因为您提到了玩家)并以此为例。
您可以从 windows 的工作方式中获取一个页面,然后将一个画布作为背景,然后在其上放置另一个画布作为您的播放器画布。您可以将播放器画布标记为“脏”或在更改时更改,并且仅在需要时重绘更改的图层。这意味着您仅在玩家移动或采取行动时更新第二个画布。
这个方法可以走得更远,你可以为 HUD 添加第三个画布,上面有游戏统计数据,只有当玩家的统计数据改变时才会改变。
html 可能看起来像这样:
<canvas id="background-canvas" style="border:1px solid #000000;"></canvas>
<canvas id="player-canvas" style="border:1px solid #000000;"></canvas>
<canvas id="hud-canvas" style="border:1px solid #000000;"></canvas>
【讨论】:
【参考方案4】:是的..有点是的。您可以使用globalCompositeOperation“绘制”现有像素。
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;
canvasborder: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>
【讨论】:
你为什么说“有点”?对我来说,这似乎是这里唯一真正的解决方案。 我说“有点”是因为合成不如重构图纸以首先显示正确的 z 分层那样灵活。合成只涉及 2 个“层”。一层是画布上的现有像素,第二层是新绘制的像素。重构以绘制适当分层的图形会产生所需的层数。 *** 很棒! 喜欢使用toString(16)
- 你教会了我一个新技巧:)
@conor909 它将数字转换为十六进制格式,然后返回为字符串,因此基本上它允许您轻松地将数字 rgb 值转换为其十六进制字符串等价物。尝试在控制台中运行上面显示的 randomColor() 函数以查看它的实际效果【参考方案5】:
或者您可以简单地使用包含要绘制的对象的数组,然后使用每个子对象的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.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 !
请注意,我没有测试该代码并将其写在我的手机上,因此可能会有拼写错误,但我希望这应该可以理解其中的原理。
【讨论】:
我认为map.sort(function (a, b) return a - b; );
应该是map.sort(function (a, b) return a.value - b.value; );
,我认为你不能只减去两个对象。以上是关于HTML5 Canvas 设置 z-index的主要内容,如果未能解决你的问题,请参考以下文章
我应该使用 HTML5 Canvas 还是 CSS3 Sprites 来为游戏对象设置动画?