d3.js在svg结构中移动元素

cuxqih21  于 2021-09-23  发布在  Java
关注(0)|答案(1)|浏览(351)

我写这封信是因为我正在努力使用d3.js(d3 selection)来移动svg中现有元素的位置。
我已经看到了很多创建新元素的例子,但是在这里,我的元素已经被创建了。
我的svg中有以下结构:

<g id='maingroup' class='main'>
  <title>titlemain</main>
  <text id='text'>textContent</text>
</g>

<g id='othergroup1' class='othergroup'>
  <title>othergroup1</title>
  <text id='text1'>textContent1</text>
  <ellipse fill="#ac08b6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
</g>

<g id='othergroup2' class='othergroup'>
  <title>othergroup2</title>
  <text id='text2'>textContent2</text>
  <ellipse fill="#23d5f6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
</g>

我的目标是将所有椭圆移动到主组中,以获得:

<g id='maingroup' class='main'>
  <title>titlemain</main>
  <text id='text'>textContent</text>
  <ellipse fill="#ac08b6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
  <ellipse fill="#23d5f6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
</g>

我已经用d3.js中的一个部分和dom操作部分成功地做到了这一点。

svg = d3.select('svg')
allellipses = svg.selectAll('ellipse').nodes()
for (ell of allellipses) {document.querySelector('.main').append(ell)}

有没有办法只使用d3.js?我想换一个 document.querySelector 通过一个d3.js函数。至少,要知道并理解附加现有元素的工作方式。
但是对于这个操作,只使用简单的dom操作可能更有效。

nbnkbykc

nbnkbykc1#

selection.remove()从dom中删除节点,并返回这些节点的选择。
可以为selection.append()提供附加给定节点的函数。
因此,我们可以删除节点,将节点用作数据数组,并输入/附加删除的椭圆:

var ellipse = svg.selectAll("ellipse").remove();

svg.select("#maingroup")
  .selectAll(null)
  .data(ellipse.nodes())
  .enter()
  .append(d=>d);
var svg = d3.select("svg");

var ellipse = svg.selectAll("ellipse").remove();

svg.select("#maingroup")
  .selectAll(null)
  .data(ellipse.nodes())
  .enter()
  .append(d=>d);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<g id='maingroup' class='main'>
  <title>titlemain</main>
  <text id='text'>textContent</text>
</g>

<g id='othergroup1' class='othergroup'>
  <title>othergroup1</title>
  <text id='text1'>textContent1</text>
  <ellipse fill="#ac08b6" cx="198.5" cy="25" rx="30" ry="20"></ellipse>
</g>

<g id='othergroup2' class='othergroup'>
  <title>othergroup2</title>
  <text id='text2'>textContent2</text>
  <ellipse fill="#23d5f6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
</g>
</svg>

当然,我们跳过数据绑定,使用selection.remove()和selection.each()将删除的元素附加到不同的父元素:

var ellipse = svg.selectAll("ellipse")
  .remove()
  .each(function() {
     svg.select("#maingroup").append(()=>this);
  })
var svg = d3.select("svg");

var ellipse = svg.selectAll("ellipse")
  .remove()
  .each(function() {
     svg.select("#maingroup").append(()=>this);
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>
<svg>
<g id='maingroup' class='main'>
  <title>titlemain</main>
  <text id='text'>textContent</text>
</g>

<g id='othergroup1' class='othergroup'>
  <title>othergroup1</title>
  <text id='text1'>textContent1</text>
  <ellipse fill="#ac08b6" cx="198.5" cy="25" rx="30" ry="20"></ellipse>
</g>

<g id='othergroup2' class='othergroup'>
  <title>othergroup2</title>
  <text id='text2'>textContent2</text>
  <ellipse fill="#23d5f6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
</g>
</svg>

使用selection.insert()而不是selection.append()可以在排序附加元素方面提供更大的灵活性。
最后,在对代码进行最小修改的情况下,我们可以使用selection.append()和返回节点的函数,并结合for循环:

var ellipses = svg.selectAll("ellipse").remove();
for(ellipse of ellipses) svg.select("#maingroup").append(()=>ellipse);
var svg = d3.select("svg");

var ellipses = svg.selectAll("ellipse").remove();
for(ellipse of ellipses) svg.select("#maingroup").append(()=>ellipse);
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.0.0/d3.min.js"></script>
<svg>
<g id='maingroup' class='main'>
  <title>titlemain</main>
  <text id='text'>textContent</text>
</g>

<g id='othergroup1' class='othergroup'>
  <title>othergroup1</title>
  <text id='text1'>textContent1</text>
  <ellipse fill="#ac08b6" cx="198.5" cy="30" rx="30" ry="20"></ellipse>
</g>

<g id='othergroup2' class='othergroup'>
  <title>othergroup2</title>
  <text id='text2'>textContent2</text>
  <ellipse fill="#23d5f6" cx="198.5" cy="25" rx="27" ry="18"></ellipse>
</g>
</svg>

当然,事先选择主组比每次迭代都选择主组更有效,而普通javascript应该更具性能。

相关问题