开发者

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 mor开发者_运维技巧e 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.).


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.


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 absolutely must flatten them to a single canvas (e.g. you want to create a data uri from the result) then use drawImage with one canvas as the source 'image'. For example, see:
    https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images#Using_other_canvas_elements

If You Want Simple Masking, Lighter, or Darker

  • Use the globalCompositeOperation property of the canvas context and use drawImage with one canvas as the source. See an example here:
    https://developer.mozilla.org/samples/canvas-tutorial/6_1_canvas_composite.html

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.


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)


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

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜