【问题标题】:D3 update circle-pack data new nodes overlap existing nodesD3更新circle-pack数据新节点与现有节点重叠
【发布时间】:2015-09-24 03:53:20
【问题描述】:

我正在关注General Update Pattern,但在分层方面遇到了问题。

使用循环包布局,我打包新数据,更新进入退出圈子元素。但是,当新元素进入时,它们会与更新的圆圈重叠。

数据键功能基于元素名称:

.data(nodes, function(d, i) { return d.name; });

所以我的圈子包有一个更新圈子(位置和大小正确)的位置,但它隐藏在其新进入父圈子的后面。

有没有办法将这些更新的节点发送到前面或在输入的圆上重新绘制它们?

--更新-- 正如关闭此问题的人所建议的那样,我尝试使用 moveToFront 实现链接到解决方案。

我在我的 update 部分中添加了以下代码(它没有改变任何东西),然后尝试在 enterexit之后添加它> 代码,也没有任何区别。

.each("end", function(d){ d3.select(this).moveToFront(); });


d3.selection.prototype.moveToFront = function() {
  return this.each(function(){
    this.parentNode.appendChild(this);
  });
};

为清楚起见,选择和更新如下所示:

// Load data into svg, join new data with old elements, if any.
var nodes = pack.nodes(postData);
node = root = postData;

groupNodes = svg.selectAll("g")
  .data(nodes, function(d, i) { return d.name; });

// Update and transition existing elements
groupNodes.select("circle")
  .transition()
  .duration(duration)
  .attr('transform', function(d) { return 'translate(' + d.x + ',' + d.y + ')'; })
  .attr('r', function(d) { return d.r; })
  .each("end", function(d){ d3.select(this).moveToFront(); });

此 moveToFront 代码对我的输出没有影响更新的圆圈仍留在输入的选择圆圈后面。

总结:问题似乎是由层次结构布局(圆形包装)引起的,该布局期望按照数据层次结构的顺序绘制圆圈。 d3 更新模式(使用进入、更新和退出选择)导致选定的更新元素在重新绘制层次结构时保留在 svg 中,并在其上绘制新层。这些节点的父节点已经正确设置,所以parentNode.appendChild 在这种情况下不会做任何事情,因为这不是问题的原因。

Here is a fiddle 来演示我的问题。我试过将moveToFront 代码放在不同的地方,没有明显的区别。 当您点击“更改数据”按钮时,它会重新绘制圆圈,但是名称在两个数据集之间重叠的任何圆圈都不会正确嵌套在圆圈包中。 “A 组”的孩子隐藏在其中一个父圈子后面。您可以通过 Inspect Element 验证节点是否存在。

更新小提琴的另一张图片:

【问题讨论】:

  • @lars-kotthoff 您链接到的解决方案不起作用。您还有其他建议吗?
  • 嗯好的,我已经重新打开了。您能否提供一个完整的示例来演示该问题?
  • @lars-kotthoff 我发布了一个 jsfiddle 来演示这个问题。有没有办法将这些隐藏节点移动到层次结构中的适当层?
  • 当一半的圆圈不可见时,我真的不明白发生了什么。我已经更改了笔划here,这对我来说看起来不错——所有的圆圈似乎都按正确的顺序排列。
  • @lars-kotthoff 我从您的小提琴中添加了另一张图片,以显示“隐藏”节点的示例。未正确着色的节点也是“更新”选择中未正确设置样式的节点的示例,但这是要解决的不同问题。

标签: javascript d3.js svg circle-pack


【解决方案1】:

D3 提供了一种方法,可以根据使用.sort() function 绑定到元素的数据对元素进行重新排序。在您的情况下,要检查的条件是元素的 .depth 属性——“更深”的元素应该出现在前面:

svg.selectAll("g")
  .sort(function (a, b) {
    if (a.depth < b.depth) return -1;
    else return 1;
  });

完整演示here

【讨论】:

    猜你喜欢
    • 2016-11-14
    • 1970-01-01
    • 2017-05-08
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    • 1970-01-01
    • 2018-11-19
    相关资源
    最近更新 更多