Apply canvas composite to only two operations

canvas, composite, javascript

Solution

Instead of drawing a mask, you can create a clipping region before you draw the actual pizza image. The code is almost the same, you basically replace the call to `ctx.fill()` with `ctx.clip()` and move the second `drawImage` down. You also need to `save`/`restore` the context state to reset the clipping region each time.

var ratio = 0;
var image = new Image();
image.src = "http://www.pizza.la-recette.net/img/pizza-001.jpg";
image.onload = function() {
    var canvas = document.querySelector("canvas");
    var ctx = canvas.getContext("2d");

    setInterval(function() {
        ratio += 0.01;
        ratio = ratio % 1;

        ctx.clearRect(0, 0, canvas.width, canvas.height);

        //Draw "empty" pizza image
        ctx.globalAlpha = 0.6;
        ctx.drawImage(image, 0, 0);

        ctx.save();

        //Set the clipping region
        ctx.beginPath();
        ctx.moveTo(image.width / 2, image.height / 2);
        ctx.arc(image.width / 2, image.height / 2, image.width / 2, -Math.PI / 2, (-Math.PI / 2) + ((Math.PI * 2) * ratio), false);
        ctx.clip();

        //Draw actual pizza image
        ctx.globalAlpha = 1;
        ctx.drawImage(image, 0, 0);     

        ctx.restore();
    }, 100);
};

Problem

I need to draw a pizza with opacity so that it looks "empty", and progressively fill the pizza with the full colored image in a clockwise manner using canvas. I started out by drawing the "empty" pizza, using the same image with a `globalAlpha` inferior to 1. Then I drew the "full" pizza right above it. Finally, I progressively draw an arc as the mask for the pizza and applied a composite operation on it, `"destination-atop"`. This effectively masks the pizza like I want it to, but with the adverse consequence of also masking the first pizza, the "empty" one. I only want it to hide the second pizza I'm drawing. So basically, I need to do a composite between only two operations, and not between everything drawn previously and everything drawn after. Here is my code: ``` var ratio = 0; var image = new Image(); image.src = "http://www.pizza.la-recette.net/img/pizza-001.jpg"; image.onload = function() { var canvas = document.querySelector("canvas"); var ctx = canvas.getContext("2d"); setInterval(function() { ratio += 0.01; ratio = ratio % 1; ctx.clearRect(0, 0, canvas.width, canvas.height); //Draw "empty" pizza image ctx.globalAlpha = 0.6; ctx.drawImage(image, 0, 0); //Draw actual pizza image ctx.globalAlpha = 1; ctx.drawImage(image, 0, 0); //Draw mask ctx.globalCompositeOperation = "destination-atop"; ctx.beginPath(); ctx.moveTo(image.width / 2, image.height / 2); ctx.arc(image.width / 2, image.height / 2, image.width / 2, -Math.PI / 2, (-Math.PI / 2) + ((Math.PI * 2) * ratio), false); ctx.fill(); }, 100); };​ ``` jsFiddle How can I do that?

Original source