1

我试图弄清楚如何使由 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矩形,但单击矩形时我没有得到任何响应。

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

有谁知道如何解决这个问题?我唯一的想法是在事件的范围矩形之上创建另一个矩形brushend,然后使用该矩形来处理点击行为,但这似乎是一种混乱的做事方式。

此外,这里是代码的小提琴。

4

2 回答 2

3

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

var extent = selector.extent();

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

这个想法是,如果选择不为空并且选择的范围与上次brushend事件中的相同,则用户单击选择而不是对其进行操作。

于 2013-06-27T17:40:37.083 回答
0

这是 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");
    }
}

这个想法是在开始拖动时保存鼠标位置而不是画笔范围,并检查释放按钮时是否发生了变化。

于 2014-08-06T20:00:06.047 回答