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

Hot*_*ost 79 d3.js force-layout

所以我有下一个用于设置节点,链接和其他元素的强制布局图代码:

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; });
};
Run Code Online (Sandbox Code Playgroud)

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

我可以做这个:

visualRoot.selectAll(".circle").remove();
Run Code Online (Sandbox Code Playgroud)

但我还有我附在的所有图像'.circles'.

无论如何,任何帮助将不胜感激,让我知道如果解释不够清楚,我会尽力解决它.

PS之间有什么区别graphData.nodesd3.selectAll('.nodes')

Gle*_*enn 114

你的答案是有效的,但对后人来说,这些方法更为通用.

从HTML中删除所有子项:

d3.select("div.parent").html("");
Run Code Online (Sandbox Code Playgroud)

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

d3.select("g.parent").selectAll("*").remove();
Run Code Online (Sandbox Code Playgroud)

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

  • 不幸的是.html("")在Safari中不起作用.适用于所有其他浏览器. (2认同)

Chr*_*che 9

我的第一个建议是你应该阅读d3.js关于选择的API:https://github.com/mbostock/d3/wiki/Selections

您必须了解enter()命令的工作原理(API).您必须使用它来处理新节点的事实具有帮助您的意义.

以下是您处理时的基本流程selection.data():

  • 首先,您要将某些数据"附加"到选择中.所以你有了:

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

    nodes.attr("r", function(d){return d.radius})
    
    Run Code Online (Sandbox Code Playgroud)
  • 然后,您必须处理新节点,为此您必须选择新节点,这是selection.enter()为以下所做的:

    var nodesEnter = nodes.enter()
        .attr("fill", "red")
        .attr("r", function(d){return d.radius})
    
    Run Code Online (Sandbox Code Playgroud)
  • 最后你肯定想要删除你不想要的节点,为此,你必须选择它们,这就是为此selection.exit()而做的.

    var nodesRemove = nodes.exit().remove()
    
    Run Code Online (Sandbox Code Playgroud)

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


Hot*_*ost 7

通过这种方式,我很容易解决它,

visualRoot.selectAll(".circle").remove();
visualRoot.selectAll(".image").remove();
Run Code Online (Sandbox Code Playgroud)

然后我重新添加了不同渲染的视觉元素,因为计算半径和颜色的代码已经改变了属性.谢谢.


ser*_*inc 5

如果要删除元素本身,请像一样使用element.remove()。如果您只想删除元素的内容,但保持元素原样,则可以使用f.ex。

visualRoot.selectAll(".circle").html(null);
visualRoot.selectAll(".image").html(null);
Run Code Online (Sandbox Code Playgroud)

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

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

d3.selectAll(".circle").attr("r", newValue);
Run Code Online (Sandbox Code Playgroud)