Búsqueda de sitios web

javascript - Crear una lista dinámica de DIVs con D3


He estado usando D3 para crear gráficos animados sofisticados, y los ejemplos son geniales. Sin embargo, estoy tratando de hacer algo que parece mucho más básico, y estoy teniendo problemas: vincular datos a una lista simple de DIVs.

Configuré enter() para inicializar elementos con opacidad 0, transition() para hacer que aparezcan gradualmente, y exit() para que se desvanezcan y se eliminen. enter() y exit() parecen funcionar bien; sin embargo, cuando una actualización contiene un elemento existente que ya está en la lista, parece que se elimina parcialmente: el DIV contenedor permanece, pero el contenido desaparece. No puedo entender por qué el contenido del elemento cambiaría de esta manera.

Mi código es el siguiente:

var data = [...];
sorted = data.sort(function(a, b) { return d3.descending(a.id, b.id); });

var tweet = tweetsBox
    .selectAll('div')
    .data(sorted, function(d) { return d.id; });

var enterDiv = tweet.enter()
    .append("div")
    .attr("class", "tweetdiv")
    .style("opacity", 0);
enterDiv.append("div")
    .attr("class", "username")
    .text(function(d) { return "@" + d.username });
enterDiv.append("div")
    .attr("class", "displayname")
    .text(function(d) { return d.displayname });
enterDiv.append("div")
    .attr("class", "date")
    .text(function(d) { return d.date });
enterDiv.append("div")
    .attr("class", "text")
    .text(function(d) { return d.text });

tweet.transition()
    .delay(200)
    .style("opacity", 1);

tweet.exit()
    .transition()
    .duration(200)
    .style("opacity", 0)
    .remove();

También configuré un jsFiddle aquí mostrando el problema.

Respuesta #1

El problema es que estás seleccionando los divs que creaste, pero creas más de un div por elemento de datos. Al actualizar, d3 intenta hacer coincidir los datos con los divs anidados. Dado que ya estás asignando una clase especial a los divs de nivel superior, la solución es muy simple. Reemplaza

.selectAll('div')

con

.selectAll('.tweetdiv')