簡體   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