D3.js 移动 svg 结构中的元素
D3.js Moving elements in the svg structure
我写信给你是因为我正在为 D3.js(D3 选择)移动 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 来做到这一点?我想用 D3.js 函数替换 document.querySelector
。至少,了解并理解它是如何附加现有元素的。
但对于此操作,仅使用简单的 DOM 操作可能更有效。
selection.remove() 从 DOM 中删除节点,返回这些节点的选择。
selection.append() 可以提供附加给定节点的函数。
所以我们可以删除节点,使用节点作为数据数组和enter/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 应该更有效。
我写信给你是因为我正在为 D3.js(D3 选择)移动 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 来做到这一点?我想用 D3.js 函数替换 document.querySelector
。至少,了解并理解它是如何附加现有元素的。
但对于此操作,仅使用简单的 DOM 操作可能更有效。
selection.remove() 从 DOM 中删除节点,返回这些节点的选择。
selection.append() 可以提供附加给定节点的函数。
所以我们可以删除节点,使用节点作为数据数组和enter/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 应该更有效。