Accepted answer

The g element is just an empty container which cannot capture click events (see documentation for pointer-events property for details).

However, mouse events do bubble up to it. Hence, the effect you desire can be achieved by first making sure that the g receives all pointer events:

.g_main {
  // ..
  pointer-events: all;

And then appending an invisible rectangle to it as a place to hover over:

viz.on("mousemove", function () {
        cx = d3.mouse(this)[0];
        cy = d3.mouse(this)[1];
        redrawline(cx, cy);
    .on("mouseover", function () {
        d3.selectAll('.line_over').style("display", "block");
    .on("mouseout", function () {
        d3.selectAll('.line_over').style("display", "none");
  .attr('class', 'click-capture')
  .style('visibility', 'hidden')
  .attr('x', 0)
  .attr('y', 0)
  .attr('width', width)
  .attr('height', height);

Working example:

As for why they work when applied to the svg element (from the docs):

Note that the ‘svg’ element is not a graphics element, and in a Conforming SVG Stand-Alone File a rootmost ‘svg’ element will never be the target of pointer events, though events can bubble to this element. If a pointer event does not result in a positive hit-test on a graphics element, then it should evoke any user-agent-specific window behavior, such as a presenting a context menu or controls to allow zooming and panning of an SVG document fragment.

Related Query

More Query from same tag