d3.js

d3.js - d3 v4 recupera el objetivo de arrastrar DOM desde la devolución de llamada de arrastre cuando `this` no está disponible



(1)

Use el segundo y el tercer argumento juntos para obtener this cuando this no esté disponible:

d3.drag().on(typename, function(d, i, n) { //here, ''this'' is simply n[i] })

Para una explicación detallada, eche un vistazo al siguiente artículo que escribí para tratar this en las funciones de flecha. El problema es diferente al suyo, pero la explicación es la misma.

Aquí hay una demostración básica, intenta arrastrar un círculo y mira la consola:

var data = d3.range(5) var svg = d3.select("body") .append("svg") .attr("width", 400) .attr("height", 100); var circle = svg.selectAll(null) .data(data) .enter() .append("circle") .attr("cy", 50) .attr("cx", function(d) { return 50 + 50 * d }) .attr("r", 10) .attr("fill", "tan") .attr("stroke", "black") .call(d3.drag() .on("start", function(d, i, n) { console.log(JSON.stringify(n[i])) }))

<script src="https://d3js.org/d3.v4.min.js"></script>

PD: estoy usando JSON.stringify en la selección D3 porque los fragmentos de pila se congelan si intentas console.log una selección D3.

Usando "esto" con una función de flecha

La mayoría de las funciones en D3.js aceptan una función anónima como argumento. Los ejemplos comunes son .attr , .style , .text , .on y .data , pero la lista es mucho más grande que eso.

En tales casos, la función anónima se evalúa para cada elemento seleccionado, en orden, que se pasa:

  1. El dato actual ( d )
  2. El índice actual ( i )
  3. El grupo actual ( nodes )
  4. this como el elemento DOM actual.

El dato, el índice y el grupo actual se pasan como argumentos, el famoso primer, segundo y tercer argumento en D3.js (cuyos parámetros se denominan tradicionalmente d , i y p en D3 v3.x). Para usar this , sin embargo, uno no necesita usar ningún argumento:

.on("mouseover", function(){ d3.select(this); });

El código anterior lo seleccionará cuando el mouse esté sobre el elemento. Compruébelo trabajando en este violín: https://jsfiddle.net/y5fwgopx/

La función de flecha

Como una nueva sintaxis de ES6, una función de flecha tiene una sintaxis más corta en comparación con la expresión de la función. Sin embargo, para un programador de D3 que usa this constantemente, existe una trampa: una función de flecha no crea su propio contexto. Eso significa que, en una función de flecha, this tiene su significado original del contexto circundante.

Esto puede ser útil en varias circunstancias, pero es un problema para un programador acostumbrado a usar this en D3. Por ejemplo, usando el mismo ejemplo en el violín anterior, esto no funcionará:

.on("mouseover", ()=>{ d3.select(this); });

Si lo duda, aquí está el violín: https://jsfiddle.net/tfxLsv9u/

Bueno, eso no es un gran problema: uno simplemente puede usar una expresión de función regular y anticuada cuando sea necesario. Pero, ¿qué pasa si quieres escribir todo tu código usando las funciones de flecha? ¿Es posible tener un código con funciones de flecha y aún así usarlo correctamente en D3?

Los argumentos segundo y tercero combinados

La respuesta es , porque this es lo mismo para los nodes[i] . La sugerencia está realmente presente en toda la API D3, cuando describe esto:

... con this como el elemento DOM actual ( nodes[i] )

La explicación es simple: dado que los nodes son el grupo actual de elementos en el DOM e i es el índice de cada elemento, los nodes[i] refieren al elemento DOM actual en sí. Es decir, this .

Por lo tanto, uno puede usar:

.on("mouseover", (d, i, nodes) => { d3.select(nodes[i]); });

Y aquí está el violín correspondiente: https://jsfiddle.net/2p2ux38s/

La documentación para d3.drag establece que el objetivo del elemento DOM del evento de arrastre estará disponible para la devolución de llamada:

Cuando se distribuye un evento específico, cada oyente será invocado con el mismo contexto y argumentos que selection.on oyentes: el dato actual d e índice i, con este contexto como el elemento DOM actual.

Pero mi devolución de llamada es una instancia de objeto y this apunta a ese objeto. Entonces, necesito otra forma de acceder al elemento DOM actual que normalmente se pasa en this . ¿Cómo puedo hacerlo?