繁体   English   中英

如何正确使用D3中的call()绑定拖动行为?

[英]How to properly use call() in D3 to bind drag behavior?

我需要创建一个矩形,让它侦听拖动事件。 根据文档,我必须先附加'rect'并调用dragR(event)

d3.select('#rectangle').on('click', function(){ new Rectangle(); });

function Rectangle(preloaded = false, box = []) {

    .......
    var dragR = d3.behavior.drag().on('drag', dragRect);

    function dragRect() {
      var e = d3.event;
      for(var i = 0; i < self.rectData.length; i++){
        d3.select(self.rectangleElement[0][0])
          .attr('x', self.rectData[i].x += e.dx )
          .attr('y', self.rectData[i].y += e.dy );
      }
      rect.style('cursor', 'move');
      updateRect();
    }

    rectangleElement = d3.select('svg').append('rect').attr('class', 'rectangle').call(dragR);

}

现在我的问题是rectangleElement到底是什么? 是功能还是其他? 谁能解释这段代码的工作流程? 另外,如果我想将另一个事件(称为“点击”)绑定到该事件,该怎么办?

编辑:@altocumulus答案带来了更多关于方法结果的细节:)

rectangleElement到底是什么

rectangleElement元素是d3选择 ,包含rect svg元素。

谁能解释这段代码的工作流程

var dragR = d3.behavior.drag().on('drag', dragRect);

在此行中,您将定义d3拖动行为 ,该行为创建拖动事件(和触摸)的事件侦听器。 使用.on()方法,可以将处理程序附加到事件。 在这里,您将函数dragRect附加到drag事件上。 drag事件是拖动元素时触发的事件(也具有dragStartdragEnd )。 该行仅定义行为,尚未链接到您的rect元素。

rectangleElement = d3.select('svg').append('rect').attr('class', 'rectangle').call(dragR);

在这行上,您正在创建rect元素。 首先选择第一个匹配的svg元素,然后在其中添加一个rect ,在新创建的rect上添加类rectangle ,最后将拖动侦听器附加到rect元素( call()函数doc )。

function dragRect() {
  var e = d3.event;
  for(var i = 0; i < self.rectData.length; i++){
     d3.select(self.rectangleElement[0][0])
     .attr('x', self.rectData[i].x += e.dx )
     .attr('y', self.rectData[i].y += e.dy );
  }
     rect.style('cursor', 'move');
     updateRect();
  }

这是drag事件的处理程序,每次触发drag事件时都会调用此函数。 此函数使用的变量不是您要提出的,而是看起来像这样更改了rect的x / y属性,然后将其移动。

如果我希望它绑定另一个事件(表示单击),该怎么办

有多种方法:创建rect元素时可以附加单击处理程序:

d3.select('svg')
    .append('rect')
    .attr('class', 'rectangle')
    .on('click', function(){ console.log('clicked'); })
    .call(dragR);

或稍后通过选择rect元素将其附加:

d3.select('rect.rectangle')
    .on('click', function(){ console.log('clicked'); })

这是on()文档 (适用于d3v3)

首先,通过使用d3.behavior.drag()我们可以知道您仍在使用D3 v3(这是v4中的d3.drag()和其他细微差别)。


您提供的代码包括在SVG元素上设置拖动行为所需的三个部分。

1.拖动行为本身

var dragR = d3.behavior.drag().on('drag', dragRect);

这是通过自动为拖动事件创建事件侦听器来处理元素上拖动手势的D3方法。 在此行为上调用.on()将注册一个处理函数(即dragRect ),该函数将由为其注册的事件触发(在您的情况下为drag )。

2.处理程序功能

function dragRect() {
  // ...
}

对于在拖动行为所应用到的元素上的拖动手势触发的每个事件,都将调用此函数。 在此功能中,您将进行图形化响应拖动手势所需的所有工作,即数据操作,DOM更新等。

3.将拖动行为应用于选择

rectangleElement = d3.select('svg').append('rect').attr('class', 'rectangle').call(dragR);

创建拖动行为实例并指定适当的事件处理函数后,可以将此行为应用于D3选择。 或者,用文档的话来说:

构造完成后,您可以使用selection.call将拖动行为应用于所选元素。

查看selection.call()文档会回答您的问题,此函数的返回值是:

无论指定函数的返回值如何,调用操作符总是返回当前选择。

因此, rectangleElement将保存对包含以前附加的<rect>的D3选择的引用。


如您self.rectangleElement[0][0] ,在v3中,选择将是一个数组数组,如在处理程序函数中可以看到的那样,在该函数中,该元素作为self.rectangleElement[0][0]访问。 但是,在初学者的级别上,您不必过多地关注实现细节。 只要知道这是D3选择,就具有定义良好的API,就足够了。


由于rectangleElement是D3选择,因此可以通过链接对selection.on()进一步调用来轻松地在其上注册更多事件处理程序:

rectangleElement.on("click", function(d) { });

为了避免在组合单击和拖动处理程序时遇到常见的陷阱,您可能需要看看Mike Bostock的Click vs. Drag Block。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM