Comment 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 graphique de disposition de force 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 j'ai besoin de redessiner les cercles du graphique (+tous les éléments ajoutés) avec une couleur et un rayon différents. Avoir un problème avec elle.
Je peux faire ceci:
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, je va essayer de le réparer.
P. S. quelle est la différence entre graphData.nodes
et d3.selectAll('.nodes')
?
5 réponses
Votre réponse fonctionnera, mais pour la postérité, ces méthodes sont plus génériques.
Supprimer tous les enfants de HTML:
d3.select("div.parent").html("");
Supprimer tous les enfants de SVG / HTML:
d3.select("g.parent").selectAll("*").remove();
L'appel .html("")
fonctionne avec mon SVG, mais cela peut être un effet secondaire de l'utilisation de innerSVG .
Mon premier conseil est que vous devriez lire l'API d3.js
sur les sélections: https://github.com/mbostock/d3/wiki/Selections
Vous devez comprendre comment fonctionne la commande enter()
(API ). Le fait que vous devez l'utiliser pour gérer de nouveaux nœuds a une signification qui vous aidera.
Ici est 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 avez à gérer de nouveaux nœuds, pour cela, vous devez sélectionner les nouveaux nœuds, c'est ce que
selection.enter()
est fait: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 sélectionner pour eux, c'est pour ça que
selection.exit()
est fait.var nodesRemove = nodes.exit().remove()
Un bon exemple de l'ensemble du processus peut également être trouvé sur le wiki de L'API: https://github.com/mbostock/d3/wiki/Selections#wiki-exit
De cette façon, je l'ai résolu très facilement,
visualRoot.selectAll(".circle").remove();
visualRoot.selectAll(".image").remove();
Et puis j'ai juste ajouté des éléments visuels qui ont été rendus différemment parce que le code pour calculer le rayon et la couleur avait changé les propriétés. Merci.
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]);
}
}`
Si vous voulez supprimer l'élément lui-même, utilisez simplement element.remove()
, comme toi. Dans le cas où vous voulez juste supprimer le contenu de l'élément, mais garder l'élément tel quel, vous pouvez utiliser F. ex.
visualRoot.selectAll(".circle").html(null);
visualRoot.selectAll(".image").html(null);
Au lieu de .html("")
(Je n'étais pas sûr des enfants de l'élément que vous voulez supprimer). Ceci conserve l'élément lui-même, mais nettoie tout le contenu inclus. Il la façon officielle de le faire , devrait donc fonctionner cross-browser.
PS: vous vouliez changer le cercle taille. Avez-vous essayé
d3.selectAll(".circle").attr("r", newValue);