Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Masking multiple shapes using globalCompositeOperation in canvas

I am attempting to draw multiple rectangles and then mask those using globalCompositeOperation 'source-in' which works great, but the issue is that when i fill my rectangles they disappear... If I only have one fill() call they all draw properly but only respect the last fill style applied.

code in question -

ctx.drawImage(self.glass.mask, 256, 375);
ctx.globalCompositeOperation = 'source-in';

ctx.rect(256, 635, 256, 75);
ctx.fillStyle = "#c65127";

ctx.rect(256, 605, 256, 25);
ctx.fillStyle = "#f5f4f0";

ctx.rect(256, 565, 256, 35);
ctx.fillStyle = "#c65127";

ctx.fill();

The code above works properly. But if I do this, and remove the mask -

ctx.beginPath();
ctx.rect(0, 256, 256, 75);
ctx.fillStyle = "#c65127";
ctx.fill();

ctx.beginPath();
ctx.rect(0, 226, 256, 25);
ctx.fillStyle = "#f5f4f0";
ctx.fill();

ctx.beginPath();
ctx.rect(0, 186, 256, 35);
ctx.fillStyle = "#222";
ctx.fill();

I have each rectangle and they respect their fill styles. Problem is when I enable the mask they are no longer visible.

Is there a limitation to the number of elements you can have under globalCompositeOperation 'source-in' or am I just missing something simple?

here are some fiddles -

http://jsfiddle.net/ENtXs/ - working as expected but not respecting the fill styles.

http://jsfiddle.net/ENtXs/1/ - Removing mask to show all elements

http://jsfiddle.net/ENtXs/2/ - Adding beginPath() and fill() elements respect fill styles. ( no masking)

http://jsfiddle.net/ENtXs/3/ - Adding the mask back ( nothing shows up anymore )

http://jsfiddle.net/ENtXs/4/ - Only having one rectangle with the same code as #3 works properly.

like image 233
Drew Dahlman Avatar asked Oct 22 '13 14:10

Drew Dahlman


People also ask

What is globalcompositeoperation in the canvas API?

The CanvasRenderingContext2D .globalCompositeOperation property of the Canvas 2D API sets the type of compositing operation to apply when drawing new shapes. See also Compositing and clipping in the Canvas Tutorial.

What is globalcompositeoperation in AutoCAD?

The globalCompositeOperation property sets or returns how a source (new) image are drawn onto a destination (existing) image. source image = drawings you are about to place onto the canvas.

How to use globalcompositeoperation with konva framework?

globalCompositeOperation Documentation. With Konva framework you can set globalCompositeOperation or blending mode operations with globalCompositeOperation property. Instructions: drag red rectangle over text and see how they will be drawing together. Enjoying Konva?

What is the purpose of the globalcompositeoperation property?

The globalCompositeOperation property sets or returns how a source (new) image are drawn onto a destination (existing) image. source image = drawings you are about to place onto the canvas. destination image = drawings that are already placed onto the canvas. Default. Displays the source image over the destination image


1 Answers

SOLVED

I believe the issue is with globalCompositeOperation 'source-in'. What I wound up doing was creating a buffer canvas which I draw my shapes on, then taking that image data and drawing it into my primary canvas and apply the GCO to that.

here's a working fiddle - http://jsfiddle.net/ENtXs/5/

code in question:

// Canvas and Buffers
var canvas = document.getElementById('canvas');
var buffer = document.getElementById('buffer');
var ctx = canvas.getContext('2d');
var buffer_ctx = buffer.getContext('2d');

// sizing
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;

buffer.height = window.innerHeight;
buffer.width = window.innerWidth;

// mask image
var mask = new Image();
mask.onload = function () {
    drawBuffer();
}

mask.src = 'http://drewdahlman.com/experiments/masking/highball_mask.png';

function drawBuffer() {
    buffer_ctx.beginPath();
    buffer_ctx.rect(0, 256, 256, 75);
    buffer_ctx.fillStyle = "#c65127";
    buffer_ctx.fill();

    buffer_ctx.beginPath();
    buffer_ctx.rect(0, 226, 256, 25);
    buffer_ctx.fillStyle = "#f5f4f0";
    buffer_ctx.fill();

    buffer_ctx.beginPath();
    buffer_ctx.rect(0, 186, 256, 35);
    buffer_ctx.fillStyle = "#222";
    buffer_ctx.fill();

    var image = buffer.toDataURL("image/png");
    var img = new Image();
    img.onload = function(){
        buffer_ctx.clearRect(0,0,buffer.width,buffer.height);
        ctx.drawImage(mask,0,0);
        ctx.globalCompositeOperation = 'source-in';
        ctx.drawImage(img,0,0);
    }
    img.src = image;
}
like image 84
Drew Dahlman Avatar answered Oct 15 '22 02:10

Drew Dahlman