5

I am using an HTML canvas and javascript and I need to clear all of the pixels underneath a shape created by closing a path (for example, I am using flot, and I want to make rounded corners, and to do this, I first need to remove the square corners by drawing a curve on top of the corner to remove the desired pixels).

Right now, I am doing this by just filling the shape with the same color as the background, which can imitate what I want to do, but, it is not ideal as it makes it impossible to place the chart on top of non-solid backgrounds without seeing the square corners. I know that there is a clearRect method that would do what I want to do, but with only rectangles, I need to do it with any closed shape. Is it possible, and if so, how would I do it?

brainjam
  • 18,863
  • 8
  • 57
  • 82
nsw1475
  • 300
  • 3
  • 13
  • You might want to hyperlink 'flot'. I confess I didn't know what it was, and assumed it was a typo (there are a lot of those on SO). – brainjam Jun 21 '10 at 21:49
  • @brainjam: why didn't you post the link then? [flot](http://code.google.com/p/flot/) – jigfox Jun 21 '10 at 22:07

4 Answers4

6

brainjam's code was heading in the right direction, but didn't fully solve the problem. Here's the solution:

context.save();
context.globalCompositeOperation = 'copy';
context.fillStyle = 'rgba(0,0,0,0)';
//draw shape to cover up stuff underneath
context.fill();
context.restore();
nsw1475
  • 300
  • 3
  • 13
  • for some stupidity of whatwg + browser devs, globalCompositeOperation copy doesn't work anymore as expected... (see https://bugzilla.mozilla.org/show_bug.cgi?id=366283) – fserb May 22 '12 at 16:52
  • context.globalCompositeOperation = 'destination-out' worked for me – Craig Myles Oct 29 '12 at 03:08
5

Here's an example of a function that will clear a circle from a canvas:

var clearCircle = function(x, y, radius)
{
    context.save();
    context.globalCompositeOperation = 'destination-out';
    context.beginPath();
    context.arc(x, y, radius, 0, 2 * Math.PI, false);
    context.fill();
    context.restore();
};
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • im not sure if save() and restore() are absolutely necessary, are they? i found it works without on firefox and chrome. i dont know about ie. – Octopus Oct 28 '14 at 23:32
  • @Octopus, save/restore will put the `globalCompositeOperation` value back to what it was originally. Alternatively you could preserve just that value and reset it. That may be faster -- you'd have to test it. – Drew Noakes Oct 29 '14 at 13:48
4

I think what you want is a clipping region, defined by the clip() function. The latter takes a bunch of paths. Here's an example.

This is a little different from what you are specifically asking (which is to remove pixels after drawing them), but actually not drawing the pixels in the first place is probably better, if I understand your requirements correctly.

Edit: I now think I understand that what you want to do is clear pixels to transparent black. To do that, after having defined your paths, do something like this:

context.fillStyle = 'rgba(0,0,0,0)';
context.fill();

The first statement sets the fill color to transparent black.

brainjam
  • 18,863
  • 8
  • 57
  • 82
  • the problem is that I am writing a plugin for flot, and the border of the plot as well as other elements on the plot has already been drawn before my plugin is called, and so clip() will not work as, from what I understand, it only prevents drawing, and does not remove. If this were not the case, this would be the perfect solution. – nsw1475 Jun 21 '10 at 21:17
  • @nsw1475, I've added a second method that I think does what you want. – brainjam Jun 21 '10 at 22:14
3

Use globalCompositeOperation = 'destination-out' instead of 'copy', it will erase all pixels of the shape in the canvas.

See all kinds of composition here

very usefull !

Sparkup
  • 3,686
  • 2
  • 36
  • 50
jume
  • 31
  • 1