D3js mouseover tooltip

It took me three hours, but I added a mouseover tooltip to my LoL netlog graphs. It turns out there’s three ways to do this.

  1. Use svg:title or svg:text and rely on the default browser hover action to show it. Totally ghetto, but it does work.
  2. Catch mouseover events on your actual chart elements. If you bound your data sensibly, the event handler gets the datum that was bound to the element that got the event passed right to it. This works great for bar charts as long as you don’t mind the popups only showing up on the bars, not the whitespace. Not so good for line charts or other things.
  3. Add an overlay to the entire chart area you want to capture events in. Unfortunately no useful data is bound if you do this. So you have to use d3.mouse() to get the relative X,Y in pixels of the mouse position, then shove that through scale.invert() to map that back to data space. Here’s a demo of that technique. It’s a lot more work, but now you have mouse events for the whole chart area, not just the marks.

I went for option #3 and really it looks pretty great. The other tricky part is I was reading the timestamp from the X axis of my time series chart, but then finding the specific row of timeseries data that corresponds to that timestamp is not so easy. I ended up doing a linear search in my data array; not awesome, but will work OK for me.

The other half of the problem is displaying the tooltips. I ended up going with a div element with visiblity toggled by mouseenter/mouseleave. The tooltip is positioned absolutely with CSS, and the mousemove handler positions the tooltip relative to the event pageX and pageY. Important to make sure the tooltip div doesn’t grab the mouse events. I did that with positioning, but probably better to use the pointer-events CSS option.