D3.js: 将参数传递给事件处理程序
D3.js: Passing a parameter to event handler
我在 Angular 2 组件中有一个 D3.js 代码,用 TypeScript 编写。
自然地,我倾向于以 OOP 方式包装东西,以便组件可以(例如)重复使用多次。
但是,我在将某些内容传递给事件处理程序时遇到问题。
this.simulation = d3.forceSimulation()
...
.on("tick", this.onSimulationTick);
onSimulationTick()
只能访问全局变量,d3.event
和this
:
When a specified event is dispatched, each listener will be invoked with the this context as the simulation.
全局变量不是一个选项,破坏了封装。我无法将任何内容附加到 d3.event
,而且我不知道它们的上下文含义。
在处理程序中,我想访问一些属于 class 成员的东西。所以最好是传递组件对象。
如何将任何内容传递给处理程序?如何使用它的上下文?
也许我可以以某种方式使用 lambda,比如
.on("tick", () => onSimulationTick.that = this, onSimulationTick );
这是缩短的组件代码:
@Component({
templateUrl: "dependencies-graph.component.html",
styleUrls: ["dependencies-graph.component.css"],
selector: 'wu-dependencies-graph',
})
export class DependenciesGraphComponent implements OnInit, OnChanges {
// Data
_dependencies: DependenciesData;
private jsonData;
// Selections
private zoomingGroup;
// Behaviors
private simulation;
private zoom;
private center: Point;
private initVisualisation() {
this.zoomingGroup = d3.select("svg #zoomingGroup");
...
this.simulation = d3.forceSimulation()
...
.on("tick", this.onSimulationTick);
}
static onSimulationTick() {
???.zoomingGroup.selectAll(".myEdge")
.attr("x1", function(item) { return item.source.x; })
.attr("y1", function(item) { return item.source.y; })
.attr("x2", function(item) { return item.target.x; })
.attr("y2", function(item) { return item.target.y; });
???.zoomingGroup.selectAll(".myGroup")
.attr("transform", function(d){return "translate("+d.x+","+d.y+")"});
}
您可以使用 Function.prototype.bind 方法绑定上下文::
private initVisualisation() {
this.zoomingGroup = d3.select("svg #zoomingGroup");
...
this.simulation = d3.forceSimulation()
...
.on("tick", this.onSimulationTick.bind(this));
}
static onSimulationTick() {
this.zoomingGroup.selectAll(".myEdge")
.attr("x1", function(item) { return item.source.x; })
.attr("y1", function(item) { return item.source.y; })
.attr("x2", function(item) { return item.target.x; })
.attr("y2", function(item) { return item.target.y; });
this.zoomingGroup.selectAll(".myGroup")
.attr("transform", function(d){return "translate("+d.x+","+d.y+")"});
}
如果你想传递额外的参数 arrow function 可能是更好的选择:
.on("tick", () => this.onSimulationTick(somethingElse));
我在 Angular 2 组件中有一个 D3.js 代码,用 TypeScript 编写。
自然地,我倾向于以 OOP 方式包装东西,以便组件可以(例如)重复使用多次。
但是,我在将某些内容传递给事件处理程序时遇到问题。
this.simulation = d3.forceSimulation()
...
.on("tick", this.onSimulationTick);
onSimulationTick()
只能访问全局变量,d3.event
和this
:
When a specified event is dispatched, each listener will be invoked with the this context as the simulation.
全局变量不是一个选项,破坏了封装。我无法将任何内容附加到 d3.event
,而且我不知道它们的上下文含义。
在处理程序中,我想访问一些属于 class 成员的东西。所以最好是传递组件对象。
如何将任何内容传递给处理程序?如何使用它的上下文?
也许我可以以某种方式使用 lambda,比如
.on("tick", () => onSimulationTick.that = this, onSimulationTick );
这是缩短的组件代码:
@Component({
templateUrl: "dependencies-graph.component.html",
styleUrls: ["dependencies-graph.component.css"],
selector: 'wu-dependencies-graph',
})
export class DependenciesGraphComponent implements OnInit, OnChanges {
// Data
_dependencies: DependenciesData;
private jsonData;
// Selections
private zoomingGroup;
// Behaviors
private simulation;
private zoom;
private center: Point;
private initVisualisation() {
this.zoomingGroup = d3.select("svg #zoomingGroup");
...
this.simulation = d3.forceSimulation()
...
.on("tick", this.onSimulationTick);
}
static onSimulationTick() {
???.zoomingGroup.selectAll(".myEdge")
.attr("x1", function(item) { return item.source.x; })
.attr("y1", function(item) { return item.source.y; })
.attr("x2", function(item) { return item.target.x; })
.attr("y2", function(item) { return item.target.y; });
???.zoomingGroup.selectAll(".myGroup")
.attr("transform", function(d){return "translate("+d.x+","+d.y+")"});
}
您可以使用 Function.prototype.bind 方法绑定上下文::
private initVisualisation() {
this.zoomingGroup = d3.select("svg #zoomingGroup");
...
this.simulation = d3.forceSimulation()
...
.on("tick", this.onSimulationTick.bind(this));
}
static onSimulationTick() {
this.zoomingGroup.selectAll(".myEdge")
.attr("x1", function(item) { return item.source.x; })
.attr("y1", function(item) { return item.source.y; })
.attr("x2", function(item) { return item.target.x; })
.attr("y2", function(item) { return item.target.y; });
this.zoomingGroup.selectAll(".myGroup")
.attr("transform", function(d){return "translate("+d.x+","+d.y+")"});
}
如果你想传递额外的参数 arrow function 可能是更好的选择:
.on("tick", () => this.onSimulationTick(somethingElse));