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

Posted

技术标签:

【中文标题】如何从节点中删除所有子元素,然后以不同的颜色和大小再次应用它们?【英文标题】:How do I remove all children elements from a node and then apply them again with different color and size? 【发布时间】:2013-01-03 12:53:38 【问题描述】:

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

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') 有什么区别?

【问题讨论】:

【参考方案1】:

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

html 中删除所有子项:

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

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

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

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

【讨论】:

不幸的是 .html("") 在 Safari 中不起作用。在所有其他浏览器中都能正常工作。 @glyph:请参阅***.com/a/43661877/1587329 了解官方方法【参考方案2】:

我的第一个建议是你应该阅读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

【讨论】:

嗨,克里斯,感谢您的建议和意见。事实是,我没有新数据。数据还是一样的。一切都是一样的。我不想再做整个强制过程。据我了解(如果我错了,请纠正我)。我所要做的就是 我所要做的就是找到带有'.circle'类的dom元素及其子元素。删除它们。找到 '.node' 类的 svg 元素,并为 'applyvisualelements' 函数中描述的 svg 圆和其他视觉对象重新应用 'attach' 过程,但这一次计算半径时,计算方式会有所不同。 无论如何,我已经很容易解决了,visualRoot.selectAll(".circle").remove(); visualRoot.selectAll(".image").remove();【参考方案3】:

这样,我已经很轻松的解决了,

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

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

【讨论】:

【参考方案4】:

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

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

而不是.html("")(我不确定要删除哪个元素的子元素)。这保留元素本身,但会清除所有包含的内容。它the official way to do this,所以应该可以跨浏览器工作。

PS:你想改变圆圈的大小。你试过了吗

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

【讨论】:

html(null) 在 Internet Explorer 11 中不适合我 @Robert:“空值将清除内容。”似乎是一个错误。向控制台报告了什么? 不,没有错误或警告。只返回选定的对象。所选答案中的d3.select($0).html('') 在 IE 中也不适用于我,但 d3.select($0).selectAll('*').remove() 确实有效。 @Robert:你想report this吗?【参考方案5】:

从节点中删除所有元素:

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

【讨论】:

你接缝引用一些东西,来源是什么? 你真的需要从它们自己的节点中删除所有这些节点吗?当然,DOM 推荐的方法就足够了,因为节点不会脱离当前节点,也不需要被撕开。 var element = document.getElementById("top"); while (element.firstChild) element.removeChild(element.firstChild);

以上是关于如何从节点中删除所有子元素,然后以不同的颜色和大小再次应用它们?的主要内容,如果未能解决你的问题,请参考以下文章

更改所有子元素的字体大小和颜色

jQuery修炼心得-DOM节点的删除

DOM节点的删除(jQuery)

二叉查找树中元素的删除操作

DOM节点删除之empty和remove区别

Jquery 4种移除 清空元素的方法