Javascript 在 HTML5 Canvas 中实现图层

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4422907/
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-23 12:20:45  来源:igfitidea点击:

Implementing Layers in HTML5 Canvas

javascripthtmlcanvas

提问by Tower

I am about to implement Photoshop-like Layers in HTML5 Canvas. Currently I have two ideas. The first and maybe the simpler idea is to have a Canvas element for each layer like:

我即将在 HTML5 Canvas 中实现类似 Photoshop 的图层。目前我有两个想法。第一个也许更简单的想法是为每一层都有一个 Canvas 元素,例如:

<canvas id="layerName" width="320" height="240" style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
<canvas id="layerName" width="320" height="240" style="position: absolute; left: 0; top: 0; z-index: 2;"></canvas>
<canvas id="layerName" width="320" height="240" style="position: absolute; left: 0; top: 0; z-index: 3;"></canvas>

This way when you draw to a layer -- it actually goes to that "layer". Layers with transparent positions can be seen through to below layers (Canvases). Layer stacking is controlled with z-indexproperty.

这样,当您绘制到图层时 - 它实际上会转到该“图层”。可以看到具有透明位置的图层到下面的图层(画布)。图层堆叠由z-index属性控制。

The second idea is to use a single Canvas element and implement some logic to handle layers like in this case:

第二个想法是使用单个 Canvas 元素并实现一些逻辑来处理层,例如在这种情况下:

<!DOCTYPE html>
<html>
    <head>
        <title>Test</title>
        <script>
            window.addEventListener('load', function() {
                var canvas = document.getElementById("canvas");  
                var ctx = canvas.getContext("2d");  

                var order = 0;

                function drawLayer1() {
                    ctx.fillStyle = "rgb(200,0,0)";
                    ctx.fillRect (10, 10, 55, 50);
                }

                function drawLayer2() {
                    ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
                    ctx.fillRect (30, 30, 55, 50);
                }

                function draw() {
                    ctx.clearRect(0, 0, 256, 256);

                    if (order === 0) {
                        drawLayer1();
                        drawLayer2();
                    }
                    else {
                        drawLayer2();
                        drawLayer1();
                    }
                }

                setInterval(draw, 250);
                setInterval(function() {
                    order = 1 - order;
                }, 200);
            }, false);
        </script>
    </head>
    <body>
        <canvas id="canvas" width="256px" height="256px"></canvas>
    </body>
</html>

In the above code the two layers will change stacking order every 200msec.

在上面的代码中,两层将每 200 毫秒更改一次堆叠顺序。

So, the question is that which way would be the best way? What are the pros and cons of both approaches?

所以,问题是哪种方式是最好的方式?两种方法的优缺点是什么?

回答by Ant

If you want to use a single canvas element and have multiple layers inside it, you might want to look at my library:

如果您想使用单个画布元素并在其中包含多个图层,您可能需要查看我的库:

It uses a damaged rect system to reduce the amount of repainting done every time the canvas changes, so not only do you get layers (which can be nested), but you also get optimised redraws.

它使用损坏的 rect 系统来减少每次画布更改时重新绘制的次数,因此您不仅可以获得图层(可以嵌套),还可以获得优化的重绘。

Here's a simple demo:

这是一个简单的演示:

回答by moeffju

Using multiple canvases should be faster, because the canvas gets drawn off-screen and then just blitted to the screen by the browser. You put the burden of switching layers on the browser, which just has to move some rectangles of graphics data around.

使用多个画布应该更快,因为画布是在屏幕外绘制的,然后被浏览器直接传送到屏幕上。您将切换图层的负担放在浏览器上,浏览器只需要移动一些图形数据的矩形即可。

If you do the layering yourself, you have more control, but the burden is on the JS and the JS engine to do all the work. I would avoid this if I had a choice, but if you're going for layer effects that work on the underlying layers, this might be your only choice.

如果你自己做分层,你有更多的控制权,但所有工作的负担都在 JS 和 JS 引擎上。如果我有选择,我会避免这种情况,但如果您要在底层工作的图层效果,这可能是您唯一的选择。

回答by firemonkey

Setting the container div relative ought to have prevented that layer-overwrite issue. Try setting the position on the "occluded text" - e.g. if it's currently absolue it will obvious go in the same region as the top left of the relative stuff.

设置容器 div 相对应该可以防止层覆盖问题。尝试在“被遮挡的文本”上设置位置 - 例如,如果它当前是绝对的,它显然会与相关内容的左上角位于同一区域。

And it's probably obvious but, by the order of divs in the html you can eliminate the use of the z axis. If you want your stuff to be generic (and for other developers too), use the z axis but store a baseline to which you add your layer indices (so that baseline can be tweaked when using other code using z-axis in a problematic way).

这可能很明显,但是,按照 html 中 div 的顺序,您可以消除 z 轴的使用。如果你希望你的东西是通用的(对于其他开发者也是如此),请使用 z 轴,但存储一个基线,你可以向其中添加图层索引(以便在以有问题的方式使用其他使用 z 轴的代码时可以调整基线)。