html5 - canvas element - Multiple layers

2019-01-02 14:08发布

Without any extension library, is it possible to have multiple layers in the same canvas element?

So if I do a clearRect on the top layer, it will not erase the bottom one?

Thanks.

6条回答
荒废的爱情
2楼-- · 2019-01-02 14:45

You might also checkout http://www.concretejs.com which is a modern, lightweight, Html5 canvas framework that enables hit detection, layering, and lots of other peripheral things. You can do things like this:

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();
查看更多
与风俱净
3楼-- · 2019-01-02 14:46

No, however, you could layer multiple <canvas> elements on top of each other and accomplish something similar.

<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>

Draw your first layer on the layer1 canvas, and the second layer on the layer2 canvas. Then when you clearRect on the top layer, whatever's on the lower canvas will show through.

查看更多
情到深处是孤独
4楼-- · 2019-01-02 14:57

I was having this same problem too, I while multiple canvas elements with position:absolute does the job, if you want to save the output into an image, that's not going to work.

So I went ahead and did a simple layering "system" to code as if each layer had its own code, but it all gets rendered into the same element.

https://github.com/federicojacobi/layeredCanvas

I intend to add extra capabilities, but for now it will do.

You can do multiple functions and call them in order to "fake" layers.

查看更多
旧人旧事旧时光
5楼-- · 2019-01-02 15:06

I understand that the Q does not want to use a library, but I will offer this for others coming from Google searches. @EricRowell mentioned a good plugin, but, there is also another plugin you can try, html2canvas.

In our case we are using layered transparent PNG's with z-index as a "product builder" widget. Html2canvas worked brilliantly to boil the stack down without pushing images, nor using complexities, workarounds, and the "non-responsive" canvas itself. We were not able to do this smoothly/sane with the vanilla canvas+JS.

First use z-index on absolute divs to generate layered content within a relative positioned wrapper. Then pipe the wrapper through html2canvas to get a rendered canvas, which you may leave as-is, or output as an image so that a client may save it.

查看更多
琉璃瓶的回忆
6楼-- · 2019-01-02 15:09

You can create multiple canvas elements without appending them into document. These will be your layers:

Then do whatever you want with them and at the end just render their content in proper order at destination canvas using drawImage on context.

Example:

/* 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);

And here is some codepen: https://codepen.io/anon/pen/mQWMMW

查看更多
深知你不懂我心
7楼-- · 2019-01-02 15:10

Related to this:

If you have something on your canvas and you want to draw something at the back of it - you can do it by changing the context.globalCompositeOperation setting to 'destination-over' - and then return it to 'source-over' when you're done.

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

// Draw a red square

co.fillStyle = 'red';
co.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 whats already on the canvas

co.globalCompositeOperation = 'destination-over';



// Draw a big yellow rectangle

co.fillStyle = 'yellow';
co.fillRect(0,0,600,250);


// Now return the globalCompositeOperation to source-over and draw a
// blue rectangle

co.globalCompositeOperation = 'source-over';

co.fillStyle = 'blue';
co.fillRect(75,75,100,100);
查看更多
登录 后发表回答