html5 - canvas元素 - 多个图层

Gre*_*ire 167 html5 canvas layer

没有任何扩展库,是否可以在同一个canvas元素中有多个图层?

所以,如果我在顶层执行clearRect,它将不会删除底层?

谢谢.

jim*_*imr 253

不,但是,您可以将多个<canvas>元素叠加在一起并完成类似的操作.

<div style="position: relative;">
 <canvas id="layer1" width="100" height="100" 
   style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
 <canvas id="layer2" width="100" height="100" 
   style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
Run Code Online (Sandbox Code Playgroud)

layer1画布上绘制第一个图层,在画布上绘制第二个图层layer2.然后,当您clearRect在顶层时,下部画布上的任何内容都将显示出来.

  • @BryanGreen不正确."但是,对于零长度,单位标识符是可选的(即可以在语法上表示为<number> 0)." https://www.w3.org/TR/css3-values/#lengths (5认同)
  • 感谢您的回答.一个bemol:z-index不是zIndex;) (3认同)
  • 你可以用CSS隐藏它 - 即`display:none;`.或者只是清除画布,如果在显示图层时再次重绘它不是非常昂贵的. (3认同)

Ric*_*ard 36

与此相关:

如果你的画布上有东西,并且你想在它的背面画一些东西 - 你可以通过将context.globalCompositeOperation设置改为'destination-over'来实现它 - 然后当你''时将它返回'source-over'重做.

   var context = document.getElementById('cvs').getContext('2d');

    // Draw a red square
    context.fillStyle = 'red';
    context.fillRect(50,50,100,100);



    // Change the globalCompositeOperation to destination-over so that anything
    // that is drawn on to the canvas from this point on is drawn at the back
    // of what's already on the canvas
    context.globalCompositeOperation = 'destination-over';



    // Draw a big yellow rectangle
    context.fillStyle = 'yellow';
    context.fillRect(0,0,600,250);


    // Now return the globalCompositeOperation to source-over and draw a
    // blue rectangle
    context.globalCompositeOperation = 'source-over';

    // Draw a blue rectangle
    context.fillStyle = 'blue';
    context.fillRect(75,75,100,100);
Run Code Online (Sandbox Code Playgroud)

  • 是的,这很好,但在擦除的情况下,如所问的那样。这将同时擦除两层。这又是不正确的。 (2认同)
  • **这是令人难以置信和惊人的答案。** 非常感谢@Richard !!!!! (2认同)

jus*_*zak 23

您可以创建多个canvas元素,而无需将它们附加到文档中.这些将是你的图层:

然后随心所欲地做任何事情,最后只需使用drawImageon 在目标画布上以正确的顺序渲染其内容context.

例:

/* using canvas from DOM */
var domCanvas = document.getElementById('some-canvas');
var domContext = domCanvas.getContext('2d');
domContext.fillRect(50,50,150,50);

/* virtual canvase 1 - not appended to the DOM */
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(50,50,150,150);

/* virtual canvase 2 - not appended to the DOM */    
var canvas2 = document.createElement('canvas')
var ctx2 = canvas2.getContext('2d');
ctx2.fillStyle = 'yellow';
ctx2.fillRect(50,50,100,50)

/* render virtual canvases on DOM canvas */
domContext.drawImage(canvas, 0, 0, 200, 200);
domContext.drawImage(canvas2, 0, 0, 200, 200);
Run Code Online (Sandbox Code Playgroud)

这里有一些代码:https://codepen.io/anon/pen/mQWMMW

  • @SCLeo你说"性能杀手.慢约10倍"是完全错误的.根据使用单个DOM画布的用例和渲染屏幕外的画布比在DOM中堆叠画布更快.常见的错误是基准渲染调用,画布绘制调用可以定时,DOM渲染在Javascripts上下文之外并且无法定时.结果是DOM堆叠画布没有得到基准测试中包含的合成渲染(由DOM完成). (4认同)
  • @ Blindman67对不起,这是我的错.我测试并发现使用多个屏幕外的画布运行非常流畅.我仍然不确定为什么该基准测试表明使用屏幕外画布很慢. (4认同)

小智 6

我也遇到了同样的问题,我同时使用了多个具有position:absolute的画布元素,如果您要将输出保存到图像中,那将是行不通的。

因此,我继续进行了一个简单的分层“系统”以进行编码,就好像每个层都有自己的代码一样,但是所有这些都被渲染到同一元素中。

https://github.com/federicojacobi/layeredCanvas

我打算添加额外的功能,但现在可以了。

您可以执行多种功能并调用它们以“伪造”图层。


Eri*_*ell 5

您还可以查看 http://www.concretejs.com,这是一个现代、轻量级的 Html5 画布框架,支持命中检测、分层和许多其他外围设备。你可以做这样的事情:

var wrapper = new Concrete.Wrapper({
  width: 500,
  height: 300,
  container: el
});

var layer1 = new Concrete.Layer();
var layer2 = new Concrete.Layer();

wrapper.add(layer1).add(layer2);

// draw stuff
layer1.sceneCanvas.context.fillStyle = 'red';
layer1.sceneCanvas.context.fillRect(0, 0, 100, 100);

// reorder layers
layer1.moveUp();

// destroy a layer
layer1.destroy();
Run Code Online (Sandbox Code Playgroud)