views:

2613

answers:

4

I've built an analytical data visualization engine for Canvas and have been requested to add tooltip-like hover over data elements to display detailed metrics for the data point under the cursor.

For simple bar & Gaant charts, tree graphs and node maps with simple square areas or specific points of interest, I was able to implement this by overlaying absolutely-positioned DIVs with :hover attributes, but there are some more complicated visualizations such as pie charts and a traffic flow rendering which has hundreds of separate areas defined by bezeir curves.

Is is possible to somehow attach an overlay, or trigger an event when the user mouses over a specific closed path?

Each area for which hover needs to be specified is defined as follows:

context.beginPath();
context.moveTo(segmentRight, prevTop);
context.bezierCurveTo(segmentRight, prevTop, segmentLeft, thisTop, segmentLeft, thisTop);
context.lineTo(segmentLeft, thisBottom);
context.bezierCurveTo(segmentLeft, thisBottom, segmentRight, prevBottom, segmentRight, prevBottom);
/*
 * ...define additional segments...
 */
// <dream> Ideally I would like to attach to events on each path:
context.setMouseover(function(){/*Show hover content*/});
// </dream>
context.closePath();

Binding to an object like this is almost trivial to implement in Flash or Silverlight, since but the current Canvas implementation has the advantage of directly using our existing Javascript API and integrating with other Ajax elements, we are hoping to avoid putting Flash into the mix.

Any ideas?

+3  A: 

You could handle the mousemove event and get the x,y coordinates from the event. Then you'll probably have to iterate over all your paths to test if the point is over the path. I had a similar problem that might have some code you could use.

Looping over things in this way can be slow, especially on IE. One way you could potentially speed it up - and this is a hack, but it would be quite effective - would be to change the color that each path is drawn with so that it is not noticeable by humans but so that each path is drawn in a different color. Have a table to look up colors to paths and just look up the color of the pixel under the mouse.

Sam Hasler
I like the colors idea, but this visualization is using lots of gradients to indicate various points of activity.I found a pic here http://twitpic.com/cqam4 showing a sample of what I mean. For each of the colored areas, I want a mouseover to identify it by name and show some numeric stats about the point in question.
ryandenki
ryandenki
Too little precision for that. I get bleedover of color ranges for similarly colored areas. Instead, I think I'll render a separate invisible shadow canvas containing directly mapped non-gradient color value, and perform the pixel color index lookup there.
ryandenki
This works. Thanks for the inspiration
ryandenki
You're welcome, glad I could help.
Sam Hasler
A: 

This can't be done (well, at least not that easily), because objects you draw on the canvas (paths) are not represented as the same objects in the canvas. What I mean is that it is just a simple 2D context and once you drawn something on it, it completely forgets how it was drawn. It is just a set of pixels for it.

In order to watch mouseover and the likes for it, you need some kind of vector graphics canvas, that is SVG or implement your own on top of existing (which is what Sam Hasler suggested)

maksymko
+1  A: 

This could be done using the method ctx.isPointInPath, but it is not implemented in ExCanvas for IE. But another solution would be to use HTML maps, like I did for this little library : http://phenxdesign.net/projects/phenx-web/graphics/example.htm you can get inspiration from it, but it is still a little buggy.

Fabien Ménager
Ooh, I think isPointInPath is what I'm looking for since we're not trying to be compatible with IE anyway (internal use tool). Thanks!The HTML maps are similar to what I'm doing for some of the simpler visualizations, but for really complicated bezier paths I'd rather stick with what's in the canvas.
ryandenki
A: 

I would suggest overlaying an image map with proper coordinates set on the areas to match your canvas-drawn items. This way, you get tooltips AND a whole lot of other DOM/Browser functionality for free.

Quickredfox