javascript - examples - ¿Cómo puedo traer un círculo al frente con d3?
d3js charts examples (4)
En primer lugar, estoy usando d3.js para mostrar círculos de diferentes tamaños en matrices. Al pasar el ratón sobre el mouse, quiero que el círculo que se está moviendo se vuelva más grande, lo que puedo hacer, pero no tengo idea de cómo llevarlo al frente. Actualmente, una vez que se procesa, se oculta detrás de muchos otros círculos. ¿Cómo puedo arreglar esto?
Aquí hay una muestra de código:
.on("mouseover", function() {
d3.select(this).attr("r", function(d) { return 100; })
})
Intenté usar los métodos de ordenar y ordenar, pero no funcionaron. Estoy bastante seguro de que no lo hice correctamente. ¿Alguna idea?
A partir de d3 versión 4, hay un conjunto de funciones integradas que manejan este tipo de comportamiento sin necesidad de implementarlo usted mismo. Consulte la documentación de d3v4 para obtener más información.
Para resumir, para traer un elemento al frente, use selection.raise()
selection.raise ()
Vuelve a insertar cada elemento seleccionado, en orden, como el último hijo de su padre. Equivalente a:
selection.each(function() {
this.parentNode.appendChild(this);
});
A partir de mi experiencia dolorosa con IE9, el uso de parentNode.appendChild puede conducir a controladores de eventos perdidos en los nodos. Así que tiendo a usar otro enfoque, es decir, ordenar los nodos para que el seleccionado esté por encima de los demás:
.on("mouseover", function(selected) {
vis.selectAll(''.node'')
.sort(function(a, b) {
if (a.id === selected.id) {
return 1;
} else {
if (b.id === selected.id) {
return -1;
} else {
return 0;
}
}
});
})
Si usa el método moveToFront()
, asegúrese de especificar el segundo argumento para el método de unión de data()
, o sus datos no estarán sincronizados con su DOM.
d3.js une sus datos (proporcionados a un método de parse()
) con elementos DOM que usted crea. Si manipulas el DOM como se propuso anteriormente, d3.js no sabrá qué elemento DOM corresponde a qué ''punto'' de datos a menos que especifiques un valor único para cada ''punto'' de data()
en la llamada data()
como muestra la referencia API :
.data(data, function(d) { return d.name; })
Tendrás que cambiar el orden del objeto y hacer que el círculo que colocaste encima sea el último elemento añadido. Como puede ver aquí: https://gist.github.com/3922684 y según lo sugerido por nautat , debe definir lo siguiente antes de su script principal:
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
A continuación, solo tendrá que llamar a la función moveToFront
en su objeto (por ejemplo, circles
) al moveToFront
el moveToFront
sobre:
circles.on("mouseover",function(){
var sel = d3.select(this);
sel.moveToFront();
});
Editar: Según lo sugerido por Henrik Nordberg , es necesario vincular los datos al DOM utilizando el segundo argumento de .data()
. Esto es necesario para no perder enlaces a los elementos. Por favor, lea la respuesta de Henrick (y ¡vuélvala a votar!) Para obtener más información. Como consejo general, utilice siempre el segundo argumento de .data()
cuando vincula datos al DOM para aprovechar las capacidades de rendimiento completas de d3.
Editar: Como mencionó Clemens Tolboom , la función inversa sería:
d3.selection.prototype.moveToBack = function() {
this.each(function() {
this.parentNode.firstChild
&& this.parentNode.insertBefore(this, firstChild);
}
});
};