[英]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.