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


87

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

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'仍然附有所有图像。

无论如何,我们将不胜感激,如果解释不够清楚,请告诉我,我将尝试解决。

PSgraphData.nodes 和之间有什么区别d3.selectAll('.nodes')

Answers:


129

您的答案会起作用,但是对于后代来说,这些方法更为通用。

从HTML中删除所有子级:

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

从SVG / HTML中删除所有子级:

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

.html("")调用适用于我的SVG,但可能是使用innerSVG的副作用


3
不幸的是.html(“”)在Safari中不起作用。在所有其他浏览器上都可以正常工作。
glyph 2014年

1
@glyph:有关执行此操作的官方方法,请参见stackoverflow.com/a/43661877/1587329
serv-inc

8

我的第一条建议是,您应该阅读d3.js有关选择的API:https : //github.com/mbostock/d3/wiki/Selections

您必须了解enter()命令的工作方式(API)。您必须使用它来处理新节点这一事实具有一定的意义,可以为您提供帮助。

这是您处理的基本过程selection.data()

  • 首先,您要“附加”一些数据到选择中。所以你有了:

    var nodes = visualRoot.selectAll(".node")
        .data(graphData.nodes)
    
  • 然后,您可以在每次数据更改时修改所有节点(这将完全满足您的要求)。例如,如果您更改了新加载的数据集中的旧节点的半径

    nodes.attr("r", function(d){return d.radius})
    
  • 然后,您必须处理新节点,为此,您必须选择新节点,其selection.enter()用途是:

    var nodesEnter = nodes.enter()
        .attr("fill", "red")
        .attr("r", function(d){return d.radius})
    
  • 最后,您当然想要删除不再想要的节点,要执行此操作,必须选择它们,这selection.exit()是为了实现目的。

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

也可以在API Wiki上找到整个过程的一个很好的示例:https : //github.com/mbostock/d3/wiki/Selections#wiki-exit


克里斯,您好,谢谢您的建议和观点。事实是,我没有新数据。数据仍然相同。一切都一样。我不想再进行整个部队行动。据我了解(如果我错了,请纠正我)。我要做的只是
HotFrost

我要做的就是找到带有'.circle'类及其孩子的dom元素。删除它们。使用“ .node”类找到svg元素,并对svg圆和“ applyvisualelements”功能中所述的其他视觉效果重新应用“附加”过程,但是这一次将计算半径时,将以不同的方式进行计算。
HotFrost

无论如何,我都可以很容易地解决它,visualRoot.selectAll(“。circle”)。remove(); visualRoot.selectAll(“。image”)。remove();
HotFrost

7

这样,我就很容易解决了,

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

然后我只是重新添加了呈现方式不同的视觉元素,因为用于计算半径和颜色的代码更改了属性。谢谢。


6

如果要删除元素本身,则只需使用即可element.remove()。如果只想删除元素的内容,而又保持原样,则可以使用f.ex。

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

而不是.html("")(我不确定要删除哪个元素的孩子)。这将保留元素本身,但清除所有包含的内容。它是这样做的官方方法,因此应该跨浏览器工作。

PS:您想更改圆的大小。你有没有尝试过

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

html(null)在Internet Explorer 11中对我不起作用
罗伯特(Robert Robert)

@Robert:“空值将清除内容。” 好像是个错误。有报告要控制台吗?
serv-inc

不,没有错误或警告。仅返回所选对象。d3.select($0).html('')在IE中,从所选答案中选出的内容对我d3.select($0).selectAll('*').remove()也不起作用,但确实有效。
罗伯特

@Robert:您要举报吗?
serv-inc

3

要从节点中删除所有元素:

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

您希望引用一些内容,其来源是什么?
Christopher Chiche 2013年

您是否真的还需要从自己的节点中删除所有那些节点。毫无疑问,DOM推荐的方法就足够了,因为节点不会偏离当前节点,也不需要撕开。
18年

var element = document.getElementById(“ top”); while(element.firstChild){element.removeChild(element.firstChild); }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.