[whatwg] '' <canvas> element "selection buffer"

Mixing in: Re: [whatwg] Usemap and ismap for canvas tag

On Mon, 3 Mar 2008, Greg Houston wrote:
> > I would like to request that the canvas element get the same usemap and
> > ismap properties that the img element has.

On Thu, 30 Apr 2009, Ian Hickson wrote:
> I haven't added this, because for the kind of retained-mode graphics that
> this implies, SVG is a much better fit.

> However, <canvas> does now have isPointInPath() which allows one to get
> somewhat the same effect. When we add separate Path objects in the future,
> this will even allow hit testing to be done just by walking through a
> series of objects instead of recreating each shape for each hit test.

On Sat, 7 Jun 2008, Ond?i?ka wrote:
> > I've been looking for something similar to OpenGL's selection buffer -
> > that is, you can get some object ID for the given coordinates.
> >

On Fri, 18 Jul 2008, Mathieu HENRI wrote:
>> My solution to this type of problem is to render the scene on a
>> (ObjectID) back buffer using a single color per object ( which serves as
>> ID ), and retrieve the color where the user clicked.

We also use a buffer, using solid colors mapped to individual IDs.
To enable layers, simply increase the number of buffers. To be more
efficient,
you can calculate extents (bounding box of the path).

That said, using a bitmap is inefficient in Canvas because a typical Canvas
is backed by 4-byte pixels. A bitmap used for hit testing, needs only one
bit per
pixel, if used in its own layer.

We attempted to play with alpha transparency values to fit multiple objects
for hit-testing onto one canvas. Example: a red circle is drawn upon a
blue square,
using an alpha transparency multiple. Using bitwise math we can immediately
report which objects are contained given a coordinate. The method is
unstable, however,
because anti-aliasing ruins the solid-color fill, leaving a lot of noise
around the edges. Using get/putImageData would solve this, but cost a lot
of setup time.

All of that said, if you're looking to do hit tracking, you may want to be
using SVG,
or an implementation of SVG written in Canvas. You're free to use
multiple canvas objects and to use browser event handlers.

Keep in mind, you are going to chew up a lot of RAM if you're using
multiple bitmap backed
hit testing layers. It is easy though, and quick (CPU and writing time).

At some point, a path API would be helpful, of course.
At that point, you are on your way again to creating a scene graph

This is half way to a scene graph, done using prototype:
createGlyph(optional path string)
 // to append to current path, it requires that the current path was recorded
 isPointInPath
 toString
 getExtent
 drawGlyph(glyph,x,y...);

extent = glyph.getExtent;
box = { x: x, y: y, x2: x+box.width, y2: y+box.height, glyph: glyph };
boxes.push(box); /* you can use an r-tree structure if you have many many
boxes */

To find an object at a point, loop through your boxes,
find a box which contains your x/y coordinates, then run isPointInPath.
z-Index, and a style stack gives you a full scene graph.

This API can be written in Javascript without modifying the canvas specs.
I don't suggest Canvas be used to keep a graph of all objects,
but it would be helpful to have something like getExtent and toString in
the official API,
along with createGlyph/drawGlyph (to speed up rendering repeated shapes),
in a later version.

toString returns the current path, in an svg path-like format.


-Charles

Received on Thursday, 30 April 2009 16:55:19 UTC