96 votes

Comment supprimer tous les éléments enfants d'un nœud, puis les réappliquer avec une couleur et une taille différentes ?

J'ai donc le code du prochain graphique de présentation des forces pour définir les nœuds, les liens et les autres éléments :

var setLinks = function ()
{
    link = visualRoot.selectAll("line.link")
        .data(graphData.links)
        .enter().append("svg:line")
        .attr("class", "link")
        .style("stroke-width", function (d) { return nodeStrokeColorDefault; })
        .style("stroke", function (d) { return fill(d); })
        .attr("x1", function (d) { return d.source.x; })
        .attr("y1", function (d) { return d.source.y; })
        .attr("x2", function (d) { return d.target.x; })
        .attr("y2", function (d) { return d.target.y; });

    graphData.links.forEach(function (d)
    {
        linkedByIndex[d.source.index + "," + d.target.index] = 1;
    });
};

var setNodes = function ()
{
    node = visualRoot.selectAll(".node")
        .data(graphData.nodes)
        .enter().append("g")
        .attr("id", function (d) { return d.id; })
        .attr("title", function (d) { return d.name; })
        .attr("class", "node")
        .on("click", function (d, i) { loadAdditionalData(d.userID, this); })
        .call(force.drag)
        .on("mouseover", fadeNode(.1)).on("mouseout", fadeNode(1));
};

//append the visual element to the node
var appendVisualElementsToNodes = function ()
{
    node.append("circle")
        .attr("id", function (d) { return "circleid_" + d.id; })
        .attr("class", "circle")
        .attr("cx", function (d) { return 0; })
        .attr("cy", function (d) { return 0; })
        .attr("r", function (d) { return getNodeSize(d); })
        .style("fill", function (d) { return getNodeColor(d); })
        .style("stroke", function (d) { return nodeStrokeColorDefault; })
        .style("stroke-width", function (d) { return nodeStrokeWidthDefault; });

    //context menu:
    d3.selectAll(".circle").on("contextmenu", function (data, index)
    {
        d3.select('#my_custom_menu')
          .style('position', 'absolute')
          .style('left', d3.event.dx + "px")
          .style('top', d3.event.dy + "px")
          .style('display', 'block');

        d3.event.preventDefault();
    });
    //d3.select("svg").node().oncontextmenu = function(){return false;};

    node.append("image")
        .attr("class", "image")
        .attr("xlink:href", function (d) { return d.profile_image_url; })//"Images/twitterimage_2.png"
        .attr("x", -12)
        .attr("y", -12)
        .attr("width", 24)
        .attr("height", 24);

    node.append("svg:title")
        .text(function (d) { return d.name + "\n" + d.description; });
};

Maintenant, les couleurs et les dépendances de taille ont changé et je dois redessiner les cercles du graphique (+ tous les éléments ajoutés) avec une couleur et un rayon différents. J'ai des difficultés à le faire.

Je peux le faire :

visualRoot.selectAll(".circle").remove();

mais j'ai toutes les images que j'ai attachées à '.circles' toujours là.

De toute façon, toute aide sera appréciée, faites-moi savoir si l'explication n'est pas assez claire, j'essaierai de la corriger.

P.S. Quelle est la différence entre graphData.nodes y d3.selectAll('.nodes') ?

148voto

Glenn Points 3182

Votre réponse fonctionnera, mais pour la postérité, ces méthodes sont plus génériques.

Supprime tous les enfants du HTML :

d3.select("div.parent").html("");

Supprimez tous les enfants de SVG/HTML :

d3.select("g.parent").selectAll("*").remove();

En .html("") fonctionne avec mon SVG, mais c'est peut-être un effet secondaire de l'utilisation de l'option innerSVG .

9voto

Christopher Chiche Points 5348

Mon premier conseil est que vous devriez lire le d3.js API sur les sélections : https://github.com/mbostock/d3/wiki/Selections

Vous devez comprendre comment le enter() fonctionne ( API ). Le fait que vous deviez l'utiliser pour gérer de nouveaux nœuds a une signification qui vous aidera.

Voici le processus de base lorsque vous traitez avec selection.data() :

  • Vous voulez d'abord "attacher" des données à la sélection. Donc, vous avez :

      var nodes = visualRoot.selectAll(".node")
          .data(graphData.nodes)
  • Ensuite, vous pouvez modifier tous les nœuds chaque fois que les données sont modifiées (cela fera exactement ce que vous voulez). Si, par exemple, vous modifiez le rayon des anciens nœuds qui se trouvent dans le nouvel ensemble de données que vous avez chargé

      nodes.attr("r", function(d){return d.radius})
  • Ensuite, vous devez gérer les nouveaux noeuds, pour cela vous devez sélectionner les nouveaux noeuds, c'est ce que selection.enter() est fait pour :

      var nodesEnter = nodes.enter()
          .attr("fill", "red")
          .attr("r", function(d){return d.radius})
  • Enfin, vous voulez certainement supprimer les nœuds que vous ne voulez plus, pour ce faire, vous devez les sélectionner, c'est ce qu'il faut faire. selection.exit() est fait pour.

      var nodesRemove = nodes.exit().remove()

Un bon exemple de l'ensemble du processus peut également être trouvé sur le wiki API : https://github.com/mbostock/d3/wiki/Selections#wiki-exit

7voto

user194033 Points 192

De cette manière, je l'ai résolu très facilement,

visualRoot.selectAll(".circle").remove();
visualRoot.selectAll(".image").remove();

et ensuite j'ai juste ajouté à nouveau des éléments visuels qui étaient rendus différemment parce que le code pour calculer le rayon et la couleur avait changé de propriétés. Merci.

7voto

user1587329 Points 91

Si vous voulez supprimer l'élément lui-même, utilisez simplement element.remove() comme vous l'avez fait. Si vous souhaitez simplement supprimer le contenu de l'élément, tout en conservant l'élément tel quel, vous pouvez utiliser, par exemple, la méthode suivante

visualRoot.selectAll(".circle").html(null);
visualRoot.selectAll(".image").html(null);

au lieu de .html("") (Je n'étais pas sûr de savoir quels enfants de l'élément vous vouliez supprimer). Voici garde l'élément lui-même, mais nettoie tout le contenu inclus . Il s'agit de la manière officielle de procéder et devrait donc fonctionner dans tous les navigateurs.

PS : vous vouliez changer la taille des cercles. Avez-vous essayé

d3.selectAll(".circle").attr("r", newValue);

3voto

Pour supprimer tous les éléments d'un nœud :

var siblings = element.parentNode.childNodes;
for (var i = 0; i < siblings.length; i++) {
    for (var j = 0; j < siblings.length; j++) {
        siblings[i].parentElement.removeChild(siblings[j]);
    }
}`

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X