Mouse Hit-Testing on a Canvas Using a Separate Buffer's Pixel Data.

While unsuitable for such a simple example, this is a demonstration of using a separate buffer for quick and dirty mouse selection in a canvas element.

Clickable items, here circles, are given an int id (random in this example, but these could increment from 0, etc). This id is converted to a hex color which is used as a key in a dictionary, pointing to the associated Clickable object.

When the mouse is pressed, the clickables are rendered to a seperate canvas with the same dimensions, but instead of using their ordinary display color as a fill color, we use the color that derives from the clickable's id. The color is then read off of the buffer and used to look up the object from the clickables dictionary.

On first glance this technique seems overly complicated, particulary for circles where simply checking if the mouse falls into the radius of the clickable objects would be faster and easier, but it has a number of advantages: It works with arbitrarily shaped objects, it would work even if you were faking a 3d scene, and you don't have to do complicated math to translate your mouse coords if you're positioning your objects by transforming the canvas geometry with translation, scale and rotation calls. You can also easily change item depth by sorting the objects so objects can occlude one another in whatever order you wish.

There are some caveats. Canvas doesn't support aliased rendering, so you can get mis-attributed hits if you happened to click the edge of a shape whose pixel color happens to match the id color of another object. It's very dificult to select more than one object at a time. You also need to make sure your canvas background color is not a viable id.

2012-08-12