d3.mouse container

3,499 views
Skip to first unread message

Alex Reynolds

unread,
Jul 1, 2013, 5:33:32 PM7/1/13
to d3...@googlegroups.com, Alex Reynolds
I'd like to get the coordinates of the mouse-pointer's position when mousing over an svg:rect element contained within a larger svg:g group.

From the documentation for d3.mouse:

https://github.com/mbostock/d3/wiki/Selections#wiki-d3_mouse

"Returns the x and y coordinates of the current d3.event, relative to the specified container. The container may be an HTML or SVG container element, such as an svg:g or svg:svg. The coordinates are returned as a two-element array [ x, y]."

The container I would like to recover the relative pointer coordinates from is "grid_elements". Here's a snippet of what is inside the parent SVG:

<g id="grid_elements">
<g id="elements">
. . .
<rect id="region_group_41_element_rect_3" x="594" y="148" width="10" height="10" style="fill: #ff0000; cursor: default;"></rect>
. . .
</g>
</g>

In the 'mouseover' handler function, I add a console.log() call to log the mouse pointer coordinates are when the event is handled. As an example of code for an element rect:

d3.select("#region_group_41_element_rect_3").on("mouseover", addHighlightToElement41x3);

Here is the example event handler:

addHighlightToElement41x3 = function()
{
var gridElements = d3.select("#grid_elements");
console.log(d3.mouse(gridElements));
};

In the console, I see the following error message when I mouse-over the example rect:

"Uncaught TypeError: Object [object Array] has no method 'getBoundingClientRect'"

I am passing the desired container to d3.mouse() per the d3.js documentation, but I don't understand the error message. Per documentation, I would expect to see a coordinate pair for where the mouse pointer is located, relative to the origin of #grid_elements.

How might I fix this?

It is a bit difficult to make a jsFiddle from this as the application is too large, at this point. If you have thoughts but need to see code, please feel free to email me and I will send a web link in a separate email. I hope this email provides sufficient detail to explain the problem concisely. I appreciate any advice.

Regards,
Alex

Christophe Viau

unread,
Jul 1, 2013, 5:37:23 PM7/1/13
to d3...@googlegroups.com
d3.mouse needs a DOM elements instead of a d3 selection as argument:
console.log(d3.mouse(gridElements.node()));
Chris

Mike Bostock

unread,
Jul 1, 2013, 5:39:31 PM7/1/13
to d3...@googlegroups.com, Alex Reynolds
var gridElements = d3.select("#grid_elements");
console.log(d3.mouse(gridElements));

You’re passing a selection to d3.mouse when you should be passing the element directly, e.g.,

    d3.mouse(d3.select("#grid_elements").node())

Or equivalently, one of these:

    d3.mouse(document.getElementById("grid_elements"))
    d3.mouse(document.querySelector("#grid_elements"))

Of course, it’s often much easier to assign the event listener to the container that defines the coordinate system you care about. Also, it’s typically more efficient to assign the listener to the parent and let the events bubble up, rather than create separate listeners for every element. (But beware the performance-convenience trade-off; it can be convenient to bind to the children with selection.on if there is data involved.)

For example, if you bound your listener to the grid_elements container as d3.select("#grid_elements").on("mousemove", listener), then you can say:

  d3.mouse(this)

Because the `this` context within an event listener is the element the listener was assigned to. You can use d3.event.target to see which element was targeted by the mouse event.

Mike
Reply all
Reply to author
Forward
0 new messages