- From: Charles Pritchard <chuck@jumis.com>
- Date: Thu, 30 Apr 2009 16:55:19 -0700 (PDT)
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