1

I have a figure created with D3 that has tooltips that appear near a data point when I over it and that I can pin by clicking on that point. I also have the ability to change what values are plotted for the points by clicking on some text to change the "view" of the figure, and would like a pinned tooltip to follow the data point as it is repositioned, but I can't figure out how to do that. Specifically, I have two problems the following problem:

(1) I don't know how to go from the selected point to the coordinates I need to position the tooltip absolutely in the body of my page.

I've tried

tooltip.transition().duration(1000)
            .style("left", d3.select(".dot-selected").attr("cx") + 5 + "px")
            .style("top", d3.select(".dot-selected").attr("cy") - 5 + "px");

where the class "dot-selected" is present only for the selected point (a fact which I can confirm because its appearance changes), but this only results in approximately correct positioning.

(2) The tooltip's position (approximate or otherwise) seems to lag view changes. That is, when I change the view and move a data point, the tooltip seems to position where the point was, not where it is. I call the code above at the very end of a view update, so everything else should have updated, in particular, new values for "cx" and "cy" should have been assigned earlier.

orome
  • 45,163
  • 57
  • 202
  • 418
  • Use [`d3.event`](https://github.com/mbostock/d3/wiki/Selections#d3_event) to access the absolute cursor position. You can also compute the position relative to a container element using `d3.mouse`. – Lars Kotthoff Jun 26 '14 at 18:24
  • @LarsKotthoff: The mouse doesn't come into play here. The point moves because the data it's showing changes. – orome Jun 26 '14 at 18:30
  • 1
    Whoops, sorry, should have read the question properly. Anyway, for (2) it may help if you try to run everything without transitions first. – Lars Kotthoff Jun 26 '14 at 18:34
  • The solution to (1) — which I'll remove — is simply to use jQuery: for example, using `$(".dot-selected").offset().top` does the trick. But problem (2) remains: my positioning is clearly lagging the point updates as can be clearly seen by [playing with the figure](http://www.raxacoricofallapatorius.com/test/scattertest.php) (click on a point and then toggle between two of the views listed in the text above the figure). – orome Jun 26 '14 at 18:34
  • @LarsKotthoff: Getting rid of transitions didn't fix the problem reliably, but the idea set me on the right course: the positions of the points haven't been updated yet when the tooltip is repositioned , because they are transitioning. The solution that seems to work is to wrap the tooltip update in `setTimeout`. I'd prefer something that was actually triggered by the completion of the transition/update though, so that success didn't depend on picking the right timeout values. Is there such a thing? – orome Jun 26 '14 at 20:05
  • @LarsKotthoff: It seems there's something called `transition.each("end", ...` that takes a callback that's executed when transitions are done. This is almost perfect, but it executes the callback for *each* point, and I'd like it to just execute once. – orome Jun 26 '14 at 20:35
  • 1
    [This question](http://stackoverflow.com/questions/14024447/d3-js-transition-end-event) should help for that. You could also have a mutex that you set once executed. – Lars Kotthoff Jun 28 '14 at 19:21

1 Answers1

0

From the above question, I understood and I can say that use left and right attributes instead of cx and cy attributes and check what's happening. If still facing troubles then make fiddle and let me know.

saikiran.vsk
  • 1,788
  • 1
  • 10
  • 11
  • Do you mean use, for example `.attr("left")` in place of `.attr("cx")`? That just puts the tooltip in the upper left of the page; if I try `.style("left")`, it doesn't move at all. – orome Jun 26 '14 at 12:49
  • Another way to ask (1) is simply: how do I get the position in the page `body` of an SVG element (here a datapoint, where I know "cx" and "cy")? – orome Jun 26 '14 at 13:57
  • I've solved (1) by using jQuery. But problem (2) remains, and is even clearer. – orome Jun 26 '14 at 18:36