40

Is it possible to combine the contents of 2 separate canvas elements into a single canvas element?

Something like an equivalent of 'Flattening' two or more layers in Photoshop...?

I can think of a round about way, but am not so sure about it. I export the contents of both the canvi (lol) in the form of .png's, and then have a third canvas element draw both images with some sort of blending algorithm (xor, blend, negative, etc.).

Phrogz
  • 296,393
  • 112
  • 651
  • 745
Abhishek
  • 4,190
  • 11
  • 39
  • 52

4 Answers4

57

Of course you can, and you don't need any funny libraries or anything, just call drawImage with a canvas as the image.

Here is an example where I combine two canvas elements onto a third:

var can = document.getElementById('canvas1');
var ctx = can.getContext('2d');

ctx.fillStyle = 'rgba(255,0,0,.4)';
ctx.fillRect(20, 20, 20, 80);
ctx.fillStyle = 'rgba(205,255,23,.4)';
ctx.fillRect(30, 30, 40, 50);
ctx.fillStyle = 'rgba(5,255,0,.4)';
ctx.fillRect(40, 50, 80, 20);

var can2 = document.getElementById('canvas2');
var ctx2 = can2.getContext('2d');

ctx2.beginPath();
ctx2.fillStyle = "pink";
ctx2.arc(50, 50, 50, 0, Math.PI * 2, 1);
ctx2.fill();
ctx2.beginPath();
ctx2.clearRect(20, 40, 60, 20);

var can3 = document.getElementById('canvas3');
var ctx3 = can3.getContext('2d');

ctx3.drawImage(can, 0, 0);
ctx3.drawImage(can2, 0, 0);
<canvas id="canvas1" width="200" height="200" style="border: 1px solid black"></canvas>
<canvas id="canvas2" width="200" height="200" style="border: 1px solid black"></canvas>
<canvas id="canvas3" width="200" height="200" style="border: 1px solid black"></canvas>

http://jsfiddle.net/bnwpS/878/

Of course you can do it with just two (one onto the other), but three makes for a better example.

You can always change the globalCompositeOperation if you want an XOR effect or something.

Andreas
  • 21,535
  • 7
  • 47
  • 56
Simon Sarris
  • 62,212
  • 13
  • 141
  • 171
15

If You Want 'Normal' Blend Mode

  • Ensure that your canvas elements do not have a background specified in CSS. This will leave them transparent.
  • Absolutely position all your canvas elements over top of each other. For example, wrap them all in a <div class="canvas-layers"> and then use CSS like:

     /* Set to the same width/height as the canvases */
    .canvas-layers { position:relative; width:400px; height:300px }
    .canvas-layers canvas { position:absolute; top:0; left:0 }
    
  • Let the browser automatically perform the blending of semi-transparent areas over top of one another.

If You Need 'Normal' Blend Mode on a Single Canvas

If You Want Simple Masking, Lighter, or Darker

If You want Photoshop-Style Blend Modes

  • I have created a simple, lightweight, open-source library for performing Photoshop-style blend modes from one HTML Canvas context to another: context-blender. Here's the sample usage:

    // Might be an 'offscreen' canvas
    var over  = someCanvas.getContext('2d');
    var under = anotherCanvas.getContext('2d');
    
    over.blendOnto( under, 'screen', {destX:30,destY:15} );
    

    See the README for more information.

FaerAnne
  • 66
  • 7
Phrogz
  • 296,393
  • 112
  • 651
  • 745
1

You could with css position 2 (or more) canvases over each other and let each work as a layer. Im not sure Exactly how to do this with css, but i've done something similar, have to canvases over eachother, one for 2d-content and one for webgl and the user could easily swap between them

<div height="640" style="position: absolute;">
    <canvas width="640" style="position: absolute;visibility: hidden;" height="640" tabindex="1"></canvas>
    <canvas width="640" height="640" style="visibility: hidden;position: absolute;"></canvas>
</div>

I guess that code is not bullet proff nor correct, but it works. Hope this helps.

If it doesnt I would use the workaround you mentioned. (I actually made a app like that where I drew 2d shadows to an offscreen canvas and drew it over the main canvas with transparency, looked pretty neat)

Rickard
  • 678
  • 5
  • 14
  • Hey, I already have positioning working http://www1.cybermed.org/workwork/E-Klinik%20related/HTML5%20Drawing/multiple_layer_drawing.html - BUT, how do I combine two or more layers...? – Abhishek Jul 22 '11 at 10:54
  • 1
    So, do i get you right that in the end you want ONE canvas having all info. If that is the case I do believe you could just render the two canvases to a third as images or I might misunderstand your question. But for how to combine a source and a destionation you can check out this http://www.nihilogic.dk/labs/canvas_sheet/HTML5_Canvas_Cheat_Sheet.png – Rickard Jul 22 '11 at 21:03
0

I think you are looking for something like the pixastic library (Documentation).

Artjom B.
  • 61,146
  • 24
  • 125
  • 222
Tim
  • 1,938
  • 1
  • 13
  • 20