我正在使用D3库来移动维恩图中的项目。当我停止拖动时,我想确定图表中项目的位置。
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对象而不是类的实例。 所以我得到一个“未捕获的TypeError:无法读取未定义的属性'保存”
如何从dragended方法中调用我班级的另一种方法?
答案 0 :(得分:2)
如果您需要保持对类实例的引用以及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进行测试
答案 1 :(得分:0)
原则上,D3将选择,转换等回调的this
上下文绑定到它们运行的DOM元素。
通过暗示,如果您需要在词法范围意义上访问“包装对象”的this
上下文,则不能使用this
来访问它。适用于您的具体案例:
d3.select(this)
将对当前迭代的DOM元素进行操作,该元素将具有item
选择的DOM元素类型。因此,如果您的item
是例如类型为SVGCircleElement
,这将是this
函数的dragended
上下文。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-selection
和d3-drag
的最新定义,你会发现他们现在有了泛型来更明确地说明与DOM有关的this
上下文类型元素和D3回调。