Abhishek
Abhishek

Reputation: 4340

Combining two or more Canvas elements with some sort of blending

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

Upvotes: 41

Views: 49047

Answers (4)

Simon Sarris
Simon Sarris

Reputation: 63802

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.

Upvotes: 58

Tim
Tim

Reputation: 1958

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

Upvotes: 0

Phrogz
Phrogz

Reputation: 303136

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.

Upvotes: 15

Rickard
Rickard

Reputation: 677

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)

Upvotes: 1

Related Questions