将事件侦听器添加到d3画笔

时间:2013-06-27 15:45:06

标签: javascript d3.js

我正在试图弄清楚如何制作由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,然后使用它来处理点击行为,但这似乎是一种混乱的做事方式。

此外,here is a fiddle of the code.

2 个答案:

答案 0 :(得分: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事件相同,那么用户点击选择而不是操纵它。

答案 1 :(得分:0)

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

  1. 如果您拖动画笔并将其返回到其原始位置,则会触发该事件。
  2. 如果您将画笔拖过容器的末端,则在光标移动时画笔不会移动,也会触发事件。
  3. 首先,像这样设置画笔:

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

    当您开始拖动时,想法是保存鼠标位置而不是画笔范围,并在释放按钮时检查是否已更改。