[英]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
事件是拖动元素时触发的事件(也具有dragStart
和dragEnd
)。 该行仅定义行为,尚未链接到您的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.