我可以在d3.js中在SVG组之间移动SVG元素

时间:2014-05-17 16:57:11

标签: svg d3.js

我可以在SVG组之间移动SVG元素 - 不需要在幕后进行太多计算,也不在我自己的代码中制作太多代码吗? d3 api documentation提到您无法重新附加已删除的元素(?)。

在将元素从原始组中删除后重新创建元素 - 在我的代码中似乎很麻烦,对于d3和浏览器而言,如果可能的话,它可能会更加昂贵。

这也与在将元素与组关联之前定义元素有关,而不仅仅是为了在组之间真正移动元素(即,将元素从非组移动到组)。

4 个答案:

答案 0 :(得分:14)

docs you posted还提到您可以通过将函数传递给.append.insert来重新添加元素。这就是它所说的:

  

请注意,目前没有专门的API可以将删除的元素添加回文档;但是,您可以将函数传递给selection.append或selection.insert以重新添加元素。


由于在选择上使用.remove会返回该选择,您可以将删除的元素存储在变量中,然后使用.append selection.node()将其存储到新组中以获取DOM元素来自删除的选择:

var removed = yourSelection.remove();
yourTargetGroup.append(function() {
  return removed.node();
});

这是一个简单的Fiddle,它使用此技术在点击处理程序中将圆元素从一个组移动到另一个组。

答案 1 :(得分:2)

仅在DOM树中的现有节点上移动,不必删除它们,然后将这些相同的节点重新附加到不同位置即可。 d3.append() internally使用Node.appendChild(),其工作原理如下:

如果给定的子项是对文档中现有节点的引用,则appendChild()将其从其当前位置移动到新位置(在将其附加到父节点之前,无需从其父节点中删除该节点。其他节点)。

这意味着节点不能同时在文档的两个点中。因此,如果该节点已经具有父节点,则首先将其删除,然后将其附加在新位置。

正如其他答复者已经提到的,selection.append()selection.insert()在传递时将分别附加或插入该函数返回的节点。知道这一点,将DOM节点从当前位置移动到新目标所需的全部时间

target.append(() => existingNode);  // target is a D3 selection, existingNode is a native DOM node

将其保存在工具箱中,一次在多个节点之间移动也相当容易:

selectionToBeMoved.each(function() { target.append(() => this); });

看看下面的演示,看看它的实际效果。用Aquamarine上色的两个圆圈从#g1组移到#g2组。

const current = d3.select("#g1");
const target  = d3.select("#g2");

current.selectAll("circle[fill=Aquamarine]")
  .each(function() { target.append(() => this); });
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.15.0/d3.min.js"></script>

<svg>
  <g id="g1">
    <circle cx="100" cy="100" r="20" fill="Aquamarine" />
    <circle cx="150" cy="100" r="20" fill="HotPink" />
    <circle cx="200" cy="100" r="20" fill="Aquamarine" />
  </g>
  <g id="g2">
  </g>
</svg>

答案 2 :(得分:1)

你不能在D3中这样做,但是JQuery有.appendTo() function,例如。

$("#element").appendTo("#otherGroup");

答案 3 :(得分:0)

也许您可以使用多个元素来做到这一点:

d3.select('#btn').on('click', function() {
  circle.remove()
    .each(function(){
    group2.node().appendChild(d3.select(this).node());
  });
});

jsFiddle