2016-08-14 107 views
4

我正在使用D3庫來移動維恩圖內的項目。當我停止拖動時,我想確定圖中項目的位置。Typescript/D3 v4 - 在d3.drag()。on(「end」,this.dragended)中的上下文

item.call(d3.drag() 
    .on("start", this.dragstarted) 
    .on("drag", this.dragged) 
    .on("end", this.dragended) 
); 

這些是我在拖動開始,正在進行和結束時調用的函數。

dragended(d: TCMemberScenario, i: number) { 
    d3.select(this).classed("active", false); 
    d.calculateRoles(); 
    this.save(); 
} 

這是拖動結束時調用的函數。我更新了圖表中的一些內容,然後我想調用save方法。這是班上的另一種方法。但是,該變量引用D3對象而不是該類的實例。 所以我得到一個「Uncaught TypeError:無法讀取屬性'保存'未定義的」

我怎樣才能從dragended方法調用我的課程的另一種方法?

回答

6

爲了保持參照「這個」使用箭頭功能是這樣的:

item.call(d3.drag() 
    .on("start", (d, i) => this.dragstarted(d,i)) 
    .on("drag", (d, i) => this.dragged(d, i)) 
    .on("end", (d, i) => this.dragended(d, i)) 
); 
0

作爲原則問題,D3結合上選擇,轉變到DOM元素回調的this上下文等在其上他們運作。

暗示,如果您需要從詞彙範圍意義上訪問「包裝對象」的this上下文,則不能使用this來訪問它。適用於您的具體情況:

  • d3.select(this)將在當前迭代,這將有item選擇底層的DOM元素的類型DOM元素進行操作。所以,如果您的item是例如類型SVGCircleElement,這將是dragended函數的this上下文。
  • 的一種方式來訪問包裝對象this背景以及是通過創建圍繞dragended功能關閉:

您可以添加一個私有方法,以你的包裝對象,它具有save方法:

private getDragEndedHandler() { 
    let self = this; // object context to preserve 
    return function(d: TCMemberScenario, i: number) { 
    d3.select(this).classed("active", false); // D3 bound DOM element context 
    d.calculateRoles(); 
    self.save(); // closure-preserved object context 
    } 
} 

現在,當您綁定的處理程序時,您只需做到以下幾點:

item.call(d3.drag() 
    .on("start", this.dragstarted) 
    .on("drag", this.dragged) 
    .on("end", this.getDragEndedHandler()) 
); 

如果需要,可以將相同的模式應用於其他事件處理程序。

如果使用從NPM @types d3-selectiond3-drag最新的定義,你會看到,他們現在有仿製藥,以更明確瞭解有關DOM元素和D3回調this背景打字。

0

如果您需要參考保持到類實例,也拖累D3引用的元素實例,你可以定義你的監聽功能:

export class MyClass { 
    @Input() 
    radius: number = 45; 

    constructor() { 
     d3.drag() 
      .on("start", this.dragStarted(this)) 
      .on("drag", this.dragged(this)) 
      .on("end", this.dragEnded(this)); 
    } 

    private dragged(self) { 
     return function(d) { 
      // 'this' in this context will be the d3 element 

      d3.select(this) 
       .attr("cx", d.x = self.radius * Math.cos(alpha)) 
       .attr("cy", d.y = d3.event.y < 0 ? -self.radius * Math.sin(alpha) : self.radius * Math.sin(alpha)); 
     } 
    } 

    ... 

} 

測試與d3.js V4