向d3笔刷添加事件侦听器

Adding an event listener to a d3 brush

本文关键字:事件 侦听器 添加 d3      更新时间:2023-09-26

我正试图弄清楚如何让d3笔刷创建的矩形(特别是事件矩形)响应点击事件。最后,我想在这个对象上单击一次,就会弹出一个菜单,但我似乎无法获得rect元素来捕捉事件。

我尝试了以下代码:

var selector = d3.svg.brush();
var x = d3.scale.linear()
    .range([0,500])
    .domain([0,500]);
var y = d3.scale.linear()
    .range([0,500])
    .domain([0,500]);
d3.select('#myDiv')
    .append('svg')
    .attr('id','mySVG')
    .attr('height',500)
    .attr('width',500)
    .call(selector.x(x).y(y).on('brushend',bindSelect))
function bindSelect(){
    d3.select('#mySVG rect.extent')
        .on('click',function(){alert('hi mom!')})
}

bindSelect似乎发射得很好,并成功地选择了.extent矩形,但我在单击矩形时没有得到任何响应。

问题似乎是d3在单击矩形时触发了一个brushend事件,我猜这会在某个地方停止事件传播?

有人知道如何绕过这个吗?我唯一的想法是在brushend事件的范围rect之上创建另一个rect,然后用它来处理点击行为,但这似乎是一种混乱的做事方式。

此外,这里还有一个代码的小提琴。

获取您想要的事件可能有点麻烦,并且需要更改D3源代码。但是,可以将brushend事件与为笔刷提供的方法一起使用,以确定是否有人单击了笔刷矩形。

var extent = selector.extent();
function bindSelect(){
  if(!selector.empty() && !(extent < selector.extent() || extent > selector.extent())) {
    console.log("foo");
  }
  extent = selector.extent();
}

其想法是,如果选择不是空的,并且所选的范围与上次brushend事件时相同,则用户单击选择而不是操纵它。

这是Lars答案的一个稍微改进的版本,用于处理两种边缘情况:

  1. 如果拖动笔刷并将其返回到其确切的原始位置,这将触发事件
  2. 如果拖动笔刷经过容器的末端,笔刷将不会移动,而光标会移动,这也会触发事件

首先,像这样设置你的画笔:

selector.x(x).y(y).on('brushstart', saveCursorPos)
                  .on('brushend',   checkIfMoved))

然后,

var clickPos = [-1,-1];
function saveCursorPos() {
    var e = d3.event.sourceEvent;
    clickPos = [e.clientX,e.clientY];
}
function checkIfMoved() {
    var e = d3.event.sourceEvent;
    if(!selector.empty() && clickPos[0] === e.clientX && clickPos[1] === e.clientY) {
        alert("foo");
    }
}

其想法是在开始拖动时保存鼠标位置,而不是笔刷范围,并在释放按钮时检查是否发生了更改。