Buscar..


Sintaxis

  • selection.enter ()
  • selection.exit ()
  • selection.merge ()

Actualización de los datos: un ejemplo básico de selecciones de ingreso, actualización y salida

Crear un gráfico que muestre un conjunto de datos estático es relativamente simple. Por ejemplo, si tenemos esta matriz de objetos como datos:

var data = [
    {title: "A", value: 53},
    {title: "B", value: 12},
    {title: "C", value: 91},
    {title: "D", value: 24},
    {title: "E", value: 59}
];

Podemos crear un gráfico de barras donde cada barra representa una medida, llamada "título", y su ancho representa el valor de esa medida. Como este conjunto de datos no cambia, nuestro gráfico de barras solo tiene una selección "ingresar":

var bars = svg.selectAll(".bars")
    .data(data);

bars.enter()
    .append("rect")
    .attr("class", "bars")
    .attr("x", xScale(0))
    .attr("y", function(d){ return yScale(d.title)})
    .attr("width", 0)
    .attr("height", yScale.bandwidth())
    .transition()
    .duration(1000)
    .delay(function(d,i){ return i*200})
    .attr("width", function(d){ return xScale(d.value) - margin.left});

Aquí, estamos configurando el ancho de cada barra a 0 y, después de la transición, a su valor final.

Esta selección de entrada, solo, es suficiente para crear nuestro gráfico, que puede ver en este violín .

¿Pero qué pasa si mis datos cambian?

En este caso, tenemos que cambiar dinámicamente nuestro gráfico. La mejor manera de hacerlo es crear las selecciones "enter", "update" y "exit". Pero, antes de eso, tenemos que hacer algunos cambios en el código.

Primero, moveremos las partes cambiantes dentro de una función llamada draw() :

function draw(){
    //changing parts
};

Estas "partes cambiantes" incluyen:

  1. Las selecciones de entrar, actualizar y salir;
  2. El dominio de cada escala;
  3. La transición del eje;

Dentro de esa función draw() , llamamos a otra función, que crea nuestros datos. Aquí, es solo una función que devuelve una matriz de 5 objetos, seleccionando aleatoriamente 5 letras de 10 (ordenando alfabéticamente) y, para cada uno, un valor entre 0 y 99:

function getData(){
    var title = "ABCDEFGHIJ".split("");
    var data = [];
    for(var i = 0; i < 5; i++){
        var index = Math.floor(Math.random()*title.length);
        data.push({title: title[index],
            value: Math.floor(Math.random()*100)});
        title.splice(index,1);
    }
    data = data.sort(function(a,b){ return d3.ascending(a.title,b.title)});
    return data;
};

Y ahora, pasemos a nuestras selecciones. Pero antes de eso, una advertencia: para mantener lo que llamamos constancia del objeto , debemos especificar una función clave como el segundo argumento de selection.data:

var bars = svg.selectAll(".bars")
    .data(data, function(d){ return d.title});

Sin eso, nuestras barras no realizarán una transición sin problemas, y sería difícil seguir los cambios en el eje (puede ver que se elimina el segundo argumento en el violín a continuación).

Entonces, después de configurar correctamente nuestras var bars , podemos tratar con nuestras selecciones. Esta es la selección de salida:

bars.exit()
    .transition()
    .duration(1000)
    .attr("width", 0)
    .remove();

Y estas son las selecciones de ingreso y actualización (en D3 v4.x, la selección de actualización se combina con la selección de ingreso mediante merge ):

bars.enter()//this is the enter selection
    .append("rect")
    .attr("class", "bars")
    .attr("x", xScale(0) + 1)
    .attr("y", function(d){ return yScale(d.title)})
    .attr("width", 0)
    .attr("height", yScale.bandwidth())
    .attr("fill", function(d){ return color(letters.indexOf(d.title)+1)})
    .merge(bars)//and from now on, both the enter and the update selections
    .transition()
    .duration(1000)
    .delay(1000)
    .attr("y", function(d){ return yScale(d.title)})
    .attr("width", function(d){ return xScale(d.value) - margin.left});

Finalmente, llamamos a la función draw() cada vez que se hace clic en el botón:

d3.select("#myButton").on("click", draw);

Y este es el violín que muestra todas estas 3 selecciones en acción.

Fusionar selecciones

El patrón de actualización en D3 versión 3

Una comprensión correcta de cómo funcionan las selecciones "entrar", "actualizar" y "salir" es fundamental para cambiar correctamente el dataviz usando D3.

Desde la versión 3 de D3 (en realidad, desde la versión 2), este fragmento podría establecer las transiciones para las selecciones "entrar" y "actualizar" ( demostración en vivo aquí ):

var divs = body.selectAll("div")
    .data(data);//binding the data

divs.enter()//enter selection
    .append("div")
    .style("width", "0px");

divs.transition()
    .duration(1000)
    .style("width", function(d) { return d + "px"; })
    .attr("class", "divchart")
    .text(function(d) { return d; });

Dando este resultado después de la transición:

introduzca la descripción de la imagen aquí

¿Pero qué sucede con el mismo código exactamente si usamos D3 versión 4? Puedes verlo en esta demo en vivo : ¡ nada !

¿Por qué?

Cambios en el patrón de actualización en D3 versión 4

Veamos el código. Primero, tenemos divs . Esta selección enlaza los datos a <div> .

var divs = body.selectAll("div")
    .data(data); 

Luego, tenemos divs.enter() , que es una selección que contiene todos los datos con elementos no coincidentes. Esta selección contiene todos los divs en la primera vez que llamamos a la función draw , y establecemos sus anchos a cero.

divs.enter()
    .append("div")
    .style("width", "0px");

Luego tenemos divs.transition() , y aquí tenemos el comportamiento interesante: en la versión 3 de D3, divs.transition() hace que todo <div> en la selección "enter" cambie a su ancho final. ¡Pero eso no tiene sentido! divs no contiene la selección "entrar", y no debe modificar ningún elemento DOM.

Hay una razón por la que este extraño comportamiento se introdujo en la versión 2 y 3 de D3 ( fuente aquí ), y se “corrigió” en la versión 4 de D3. Por lo tanto, en la demostración en vivo de arriba, no sucede nada, ¡y se espera! Además, si hace clic en el botón, aparecerán las seis barras anteriores, porque ahora están en la selección "actualizar", y ya no en la selección "ingresar".

Para la transición que actúa sobre la selección "entrar", tenemos que crear variables separadas o, un enfoque más fácil, fusionando las selecciones :

divs.enter()//enter selection
    .append("div")
    .style("width", "0px")
    .merge(divs)//from now on, enter + update selections
    .transition().duration(1000).style("width", function(d) { return d + "px"; })
    .attr("class", "divchart")
    .text(function(d) { return d; });

Ahora, fusionamos las selecciones "enter" y "update". Vea cómo funciona en esta demostración en vivo .



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow