web-dev-qa-db-fra.com

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

J'ai donc le code de graphe de mise en page suivant pour définir des nœuds, des liens et d'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 de graphe (+ tous les éléments ajoutés) avec une couleur et un rayon différents. Avoir un problème avec ça.

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, laissez-moi savoir si l'explication n'est pas assez claire, je vais essayer de la réparer.

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

75
HotFrost

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

Supprimer tous les enfants du HTML:

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

Supprimez tous les enfants de SVG/HTML:

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

L'appel .html("") fonctionne avec mon SVG, mais il pourrait s'agir d'un effet secondaire de l'utilisation de innerSVG .

109
Glenn

Mon premier conseil est que vous devriez lire l'API d3.js À propos des sélections: https://github.com/mbostock/d3/wiki/Selections

Vous devez comprendre le fonctionnement de la commande enter() ( API ). Le fait que vous deviez l'utiliser pour gérer de nouveaux nœuds a un sens qui vous aidera.

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

  • vous souhaitez 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 d'anciens nœuds qui se trouvent dans le nouveau jeu de données que vous avez chargé

    nodes.attr("r", function(d){return d.radius})
    
  • Ensuite, vous devez gérer de nouveaux noeuds, pour cela vous devez sélectionner les nouveaux noeuds, c’est pour cela 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 dont vous ne voulez plus, pour ce faire, vous devez les sélectionner, c’est pour cela que selection.exit() est fait.

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

Vous trouverez également un bon exemple de l'ensemble du processus sur le wiki de l'API: https://github.com/mbostock/d3/wiki/Selections#wiki-exit

7
Christopher Chiche

de cette façon, je l'ai résolu très facilement,

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

et puis je viens de rajouter des éléments visuels qui ont été rendus différemment, car le code de calcul du rayon et de la couleur avait changé de propriétés. Merci.

7
HotFrost

Si vous souhaitez supprimer l'élément lui-même, utilisez simplement element.remove() , comme vous l'avez fait auparavant. Si vous souhaitez simplement supprimer le contenu de l'élément tout en le conservant tel quel, vous pouvez utiliser f.ex.

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

au lieu de .html("") (je ne savais pas quels enfants de l'élément vous souhaitez supprimer). This conserve l'élément lui-même, mais nettoie tout le contenu inclus. Il la manière officielle de le faire , devrait donc fonctionner avec plusieurs navigateurs.

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

d3.selectAll(".circle").attr("r", newValue);
4
serv-inc

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]);
    }
}`
3
user1613294