Beej's Bit Bucket

 ⚡ Tech and Programming Fun

2010-11-14

HTML5 Canvas and globalCompositeOperation

[Loading canvas images...]

(Here's the JS source. I took this lizard photo at the Arizona-Senora Desert Museum.)

I haven't had much time to post lately, but I saw a cool little "scratch off" app go by on Hacker News that I thought could be improved upon by using something in HTML5 canvas known as the globalCompositeOperation. So I coded up a demo to show it off.

The globalCompositeOperation affects how canvas drawing routines interact with the data that's being drawn upon. There are many different operations, but the default is "source-over", which the spec says: "Display the source image wherever the source image is opaque. Display the destination image elsewhere", which makes a certain kind of sense for what you usually want to do.

Another common mode is "copy", which ignores transparency. As the spec says for "copy": "Display the source image instead of the destination image."

But, in fact, there are plenty of modes. And some of them are better-supported than others. For this demo, for example, I wanted to use "source-out". Chrome and Safari seemed to be OK with it, but Firefox just left the canvas blank—not too useful. So instead I fell back on using "source-atop", which I also made to work.

(A completely different approach to this entire problem might be to record the path you've drawn and use the clip() method to mask out the image, but I have doubts that would be faster.)

This is supposed to be demo code, not production code. Nevertheless, several people have asked me how to remove the thumbnails. The answer: delete every line in the JS and HTML that mentions "thumb".

Finally, after user requests, I've added a page that shows how to refactor this demo code to make it work with multiple canvases on the same page.

Historic Comments

 Mark Filipak 2011-06-05 06:03:17

Howdy. Your getLocalCoords function can be a bit simpler. I'm looking at the initialization. I think, if <body onload="..."> is used, the loading can be simplified. I'll get back. Ciao - Mark Filipak.

function getLocalCoords(elem, event)
{
var ox = elem.offsetLeft, oy = elem.offsetTop;
while ((elem = elem.offsetParent) != null)
{
ox += elem.offsetLeft;
oy += elem.offsetTop;
}
return {'x' : event.pageX - ox, 'y' : event.pageY - oy};
}

 Peter Jones 2011-10-28 14:33:39

Hi
I've been looking for an html5 solution to replace Flash for our promotional scratchcards (no gambling!). Looks like you've cracked the main part of the problem. Are you still doing any work on it? If not would you be willing to share your source files?
Best wishes
Pete

 beej 2011-12-02 19:23:09

@Peter Jones Just "View Source" on the page. Everything's uncompressed in the index.html for ease of demonstration. Feel free to steal as you see fit.

Comments

Blog  ⚡  Email beej@beej.us  ⚡  Home page