2016-11-23 1 views
1

J'ai un ensemble de données nœudssuppression Sub sélection avec des animations

var dataNodes = [ 
    { id: 1, x: 10, y:30, text: "node 1", muteText: false }, 
    { id: 2, x: 30, y:50, text: "node 2", muteText: false }, 
    { id: 3, x: 50, y:70, text: "node 3", muteText: false } 
]; 

ajouter les éléments dans les DOM en utilisant ce type de fonction (pas mon vrai code à cause d'une grande complexité d'affaires):

function redraw(newData) { 
    var node = d3 
     .select("body") 
     .selectAll("g.node") 
     .data(dataNodes) 
     .transition().duration(500) 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")"); 

    node.enter() 
     .append("g") 
     .attr("class", "node") 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")") 
     .append("text") 
     .text(d => d.text) 
     .style("opacity", "0") 
     .transition().duration(500) 
     .style("opacity", "1"); 

    node.exit() 
     .style("opacity", "0"); 
} 

Je veux être capable de faire tout ce qui suit lorsque les données sont mises à jour:

  • add entrer nœuds
  • déjà faire des nœuds existants se déplacent avec une transition
  • cacher exitings nœuds (opacité 0), car ils peuvent réapparaître
  • lorsque les nœuds obtiennent leur propriété « muteText » changé vrai, que le texte intérieur disapear

Je suis assez à l'aise avec les 3 premiers requis mais je ne sais vraiment pas comment faire le dernier: comment puis-je supprimer (ou même changer) des sous-éléments en fonction d'un ensemble de données filtrées? Puis-je utiliser le filtre dans la fonction d3.data pour le faire? Faites-moi savoir si ma question n'est pas claire.

Répondre

2

Si vous souhaitez filtrer, faites-le sur votre sélection de mise à jour:

var node = svg 
    .selectAll("g.node") 
    .data(someData); 

    var nodeE = node.enter() 
    .append("g") 
    .attr("class", "node"); 

    nodeE.append("text") 
    .text(d => d.text); 

    // node is now UPDATE + ENTER 
    node = nodeE.merge(node); 

    // filter the text and set how you care 
    node.filter(function(d) { 
     return d.muteText 
    }) 
    .select("text") 
    .style("opacity", 1) 
    .transition() 
    .style("opacity", 0); 

    node.filter(function(d) { 
     return !d.muteText 
    }) 
    .select("text") 
    .style("opacity", 0) 
    .transition() 
    .style("opacity", 1); 

Voici un exemple en cours d'exécution:

<!DOCTYPE html> 
 
<html> 
 

 
<head> 
 
    <script data-require="[email protected]" data-semver="4.0.0" src="https://d3js.org/d3.v4.min.js"></script> 
 
    <style> 
 
    text { 
 
     fill: black; 
 
     font-family: arial; 
 
    } 
 
    </style> 
 
</head> 
 

 
<body> 
 
    <script> 
 
    var dataNodes = [{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: false 
 
    }, { 
 
     id: 2, 
 
     x: 30, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
    }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: false 
 
    }]; 
 

 
    var svg = d3.select('body') 
 
     .append('svg') 
 
     .attr('width', 500) 
 
     .attr('height', 500); 
 

 
    redraw([{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: false 
 
     }, { 
 
     id: 2, 
 
     x: 30, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
     }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: false 
 
     }]); 
 
    
 
    setTimeout(function() { 
 
     redraw([{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: true 
 
     }, { 
 
     id: 2, 
 
     x: 100, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
     }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: true 
 
     }]) 
 
    }, 2000) 
 
    
 
    setTimeout(function() { 
 
     redraw([{ 
 
     id: 1, 
 
     x: 10, 
 
     y: 30, 
 
     text: "node 1", 
 
     muteText: true 
 
     }, { 
 
     id: 2, 
 
     x: 100, 
 
     y: 50, 
 
     text: "node 2", 
 
     muteText: false 
 
     }, { 
 
     id: 3, 
 
     x: 50, 
 
     y: 70, 
 
     text: "node 3", 
 
     muteText: false 
 
     },{ 
 
     id: 4, 
 
     x: 60, 
 
     y: 90, 
 
     text: "node 4", 
 
     muteText: false 
 
     }]) 
 
    }, 4000) 
 

 
    function redraw(someData) { 
 

 
     var node = svg 
 
     .selectAll("g.node") 
 
     .data(someData); 
 

 
     var nodeE = node.enter() 
 
     .append("g") 
 
     .attr("class", "node") 
 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")"); 
 

 
     nodeE.append("text") 
 
     .text(d => d.text) 
 
     .style("opacity", 0) 
 
     .transition() 
 
     .style("opacity", 1); 
 

 
     node = nodeE.merge(node); 
 

 
     node.exit() 
 
     .style("opacity", "0"); 
 

 
     node.transition().duration(500) 
 
     .attr("transform", d => "translate(" + d.x + "," + d.y + ")"); 
 

 
     node.filter(function(d) { 
 
      return d.muteText 
 
     }) 
 
     .select("text") 
 
     .transition() 
 
     .style("opacity", 0);  
 

 
    } 
 
    </script> 
 
</body> 
 

 
</html>

+0

Merci pour votre réponse! Savez-vous si je peux faire en sorte que les nœuds entrants apparaissent et que les nœuds existants soient traduits? Les transitions semblent se heurter dans mon cas. Savez-vous aussi pourquoi j'obtiendrais une erreur "nodeE.merge n'est pas une fonction" dans un code similaire au vôtre? –

+1

@SimonBudin, voir la mise à jour de la réponse. La raison pour laquelle vous voyez 'nodeE.merge n'est pas une fonction' est probablement parce que vous utilisez d3 ** version 3 **, ma réponse est dans d3 ** version 4 **. – Mark

+0

Je vais planifier une mise à jour, merci! –