将“onclick”事件附加到 D3 图表背景

Posted

技术标签:

【中文标题】将“onclick”事件附加到 D3 图表背景【英文标题】:Attaching 'onclick' event to D3 chart background 【发布时间】:2014-05-21 10:19:27 【问题描述】:

我有一个 D3 直方图,我在其上附加了一个“onclick”事件到条形:

...
var bar = svg.selectAll(".bar")
        .data(data)
        .enter().append("g")
        .attr("class", "bar")
        .attr("transform", function(d)  return "translate(" + x(d.x) + "," + y(d.y) + ")"; )
        .on('mouseover', tip.show)
        .on('mouseout', tip.hide)
        .on('click', function(d,i) //do stuff  );
...

这完全符合预期。我还想在图表的背景上附加一个“onclick”事件(即图表中不是条形的任何地方),但我遇到了麻烦。我尝试过以几种方式附加事件,但在每种情况下,这个新事件似乎都会覆盖我的 bar-click:

一些尝试:

$("svg:not('.bar')").on("click", function() //do stuff );

$("g:not('.bar')").on("click", function() //do stuff );

var svg = d3.select("#histogram_block").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .on("click", function(d,i)
            if (d)  //do stuff
            else  //do stuff 
        ;

我假设有一种方法可以在初始化 SVG 对象时将事件处理程序添加到它,但我不知道正确的方法。

【问题讨论】:

只是一个提醒。 $("svg:not('.bar')") 表示获取所有没有 bar 类的 svgs。这并不意味着将svgs 部分放在具有bar 类的元素之外。 【参考方案1】:

该事件实际上并没有被覆盖,但两者都被触发了——SVG 和栏的onclick 处理程序。为防止这种情况,请使用.stopPropagation() 方法(请参阅the documentation)。代码如下所示:

rect.on("click", function() 
  console.log("rect");
  d3.event.stopPropagation();
);

完整示例here。与停止传播事件here 的行为进行比较。

【讨论】:

很好的例子,谢谢。您应该将其添加到答案中,因为它很短。那么是什么决定了我点击时的事件顺序呢?这里的假设似乎是矩形的点击事件首先触发,但情况总是如此吗? 事件“冒泡”DOM。 rectsvg 的子代,因此它将事件传播到 svg。这就是.stopPropagation() 起作用的原因。所以是的,rects 点击处理程序应该总是首先触发。 谢谢,但是如果有重叠的图表元素,SVG 的两个子元素会发生什么?哪个会先触发他们的点击事件? 你只能点击一个元素——鼠标位置前面的那个。此事件会通知父母,兄弟姐妹不受影响。 我将此解决方案应用于与此类似的问题。但是 svg 事件仅在某些时候触发。 bar onclick 事件每次都可以正常工作,但背景 onclick 事件仅以随机频率触发几次。知道为什么会这样吗?【参考方案2】:

在这个例子中(第 246 行:http://tributary.io/inlet/8361294)我附加了一个宽度和高度等于图表总面积的新矩形,然后附加我的鼠标(或单击)事件。

svg.append("rect")
        .attr("class": "overlay" , "width": width , "height": height)
        .on(
          "mouseover": function()  /* do stuff */ ,
          "mouseout":  function()  /* do stuff */ , 
          "click":  function()  /* do stuff */ , 
        );

【讨论】:

这似乎没有回答问题,因为这不会点击图表的背景与前景元素。

以上是关于将“onclick”事件附加到 D3 图表背景的主要内容,如果未能解决你的问题,请参考以下文章

将 onclick/ng-click 事件附加到网格数据绑定事件中的元素

将事件处理程序附加到nvd3图表的标签

如何使 SVG 元素鼠标事件通过另一个元素冒泡?

如何为我的 d3 图表标题设置文本颜色?

使用 D3 JS 将鱼眼添加到轴

jquery .on 容器元素附加到多个选择器