Búsqueda de sitios web

d3.js - Typescript/D3 v4 - Contexto de this en d3.drag().on("end", this.dragended)


Estoy usando la biblioteca D3 para mover un elemento dentro de un diagrama de Venn. Cuando dejo de arrastrar, quiero determinar la posición del elemento en el diagrama.

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

Estas son las funciones que llamo cuando el arrastre comienza, está en curso y termina.

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

Esta es la función que se llama cuando el arrastre ha terminado. Actualizo algunas cosas en el diagrama y luego quiero llamar al método guardar. Este es otro método en la clase. Sin embargo, la variable this hace referencia al objeto D3 y no a la instancia de la clase. Así que obtengo un "Uncaught TypeError: Cannot read property 'save' of undefined"

¿Cómo puedo llamar desde el método dragended a otro método de mi clase?

Respuesta #1

Para mantener la referencia a 'this', usa funciones flecha así:

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))
);

Respuesta #2

Si necesitas mantener la referencia a la instancia de la clase y también la instancia del elemento referenciado por d3 drag, puedes definir tus funciones de escucha como:

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));
        }
    }

    ...

}

Probado con d3.js v4

Artículos relacionados