如何从节点中删除所有子元素,然后再次应用不同颜色和大小的子元素?

因此,我有下一个力布局图代码设置节点,链接和其他元素:

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; });
};

现在,颜色和大小依赖关系发生了变化,我需要用不同的颜色和半径重新绘制图形圆圈(+ 所有附加元素)。有问题。

我能做到:

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

但是我把所有的图像都连接到 '.circles'上了。

无论如何,任何帮助都会受到感激,如果解释不够清楚,请告诉我,我会尽力弥补。

另外,graphData.nodesd3.selectAll('.nodes')有什么区别?

108788 次浏览

My first advice is that you should read the d3.js API about selections: https://github.com/mbostock/d3/wiki/Selections

You have to understand how the enter() command works (API). The fact that you have to use it to handle new nodes has a meaning which will help you.

Here is the basic process when you deal with selection.data():

  • first you want to "attach" some data to the selection. So you have:

      var nodes = visualRoot.selectAll(".node")
    .data(graphData.nodes)
    
  • Then you can modify all nodes each times data is changed (this will do exactly what you want). If for example you change the radius of old nodes which are in the new dataset you loaded

      nodes.attr("r", function(d){return d.radius})
    
  • Then, you have to handle new nodes, for this you have to select the new nodes, this is what selection.enter() is made for:

      var nodesEnter = nodes.enter()
    .attr("fill", "red")
    .attr("r", function(d){return d.radius})
    
  • Finally you certainly want to remove the nodes you don't want anymore, to do this, you have to select them, this is what selection.exit() is made for.

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

A good example of the whole process can also be found on the API wiki: https://github.com/mbostock/d3/wiki/Selections#wiki-exit

in this way, I have resolved it very easily,

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

and then I just re-added visual elements which were rendered differently because the code for calculating radius and color had changed properties. Thank you.

To remove all element from a node:

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

Your answer will work, but for posterity, these methods are more generic.

Remove all children from HTML:

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

Remove all children from SVG/HTML:

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

The .html("") call works with my SVG, but it might be a side effect of using innerSVG.

If you want to remove the element itself, just use element.remove(), as you did. In case you just want to remove the content of the element, but keep the element as-is, you can use f.ex.

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

instead of .html("") (I wasn't sure which element's children you want deleted). This keeps the element itself, but cleans all included content. It the official way to do this, so should work cross-browser.

PS: you wanted to change the circle sizes. Have you tried

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