2017-02-02 11 views
1

У меня есть код D3.js в компоненте Angular 2, написанный на языке TypeScript.D3.js: Передача параметра обработчику событий

Естественно, я склонен обертывать вещи способом ООП, так что компонент может быть (например) повторно использован многократно.

Однако у меня есть проблема с передачей чего-либо обработчикам событий.

this.simulation = d3.forceSimulation() 
     ... 
     .on("tick", this.onSimulationTick); 

onSimulationTick() может получить доступ только к глобальным переменным, d3.event и this:

Когда указанное событие отправляется, каждый слушатель будет вызываться с связи с этим в качестве имитации.

Глобальная переменная не является опцией, разрывает инкапсуляцию. Я ничего не могу приложить к d3.event, и я не знаю, что они подразумевают под контекстом.

В обработчике я хочу получить доступ к нескольким вещам, которые являются членами класса. Лучше всего было бы передать объект компонента.

Как я могу передать что-либо обработчику? Как я мог использовать контекст?

Может быть, я мог бы использовать лямбда в некотором роде, как

.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+")"}); 
    } 

ответ

1

Вы могли бы связать контекст с 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)); 
+0

Ha! Я полностью забыл о 'bind()'. Попытаемся. –

+0

С лямбдой мы компилируем ES5, поэтому не уверены, что это сработает. Попытка тоже –