我创建了以下文档:
<g>
<path class="line" name="gene_1" stroke="#aec7e8" d="M10.47..."></path>
<path class="line" name="gene_2" stroke="#aec7e8" d="M10.47..."></path>
<path class="line" name="gene_3" stroke="#aec7e8" d="M10.47..."></path>
...
</g>
当我鼠标悬停在每条路径上时,我想将它最后添加到svg:g中,以便它显示在其他行的顶部,但我不知道如何正确选择parentNode:
function onmouseover(d, i){
var current_gene_name = d3.select(this).attr("name"),
current_gene_pcp = d3.select(".line[name=" + current_gene_name + "]");
p1 = this.parentNode
p2 = current_gene_pcp[0].parentNode
p3 = current_gene_pcp[0][0].parentNode
//p.appendChild(this);
}
p1有效,但我想确保“this”是.line,所以我更喜欢使用current_gene_pcp,但是p2返回<html></html>
作为父级,即使p3返回正确的{{1} }。最后一个版本似乎是一个等待发生的错误。还有更好的方法吗?
答案 0 :(得分:45)
D3选择只是围绕所选元素的双重数组。正如您在p3
中找到的那样,如果需要,可以取消引用数组以查找第一个节点。但是,确实存在更好的方法:
来自selection.node()
的文档:
返回当前选择中的第一个非
null
元素。如果选择为空,则返回null
。
在你的情况下:
var dad = current_gene_pcp.node().parentNode;
但是,如果你不需要DOM句柄以外的行,你也可以直接得到它:
// Search document-wide...
var dad = document.querySelector(".line[name=" + current_gene_name + "]");
// ...or only as a child of the current DOM element
var dad = this.querySelector(".line[name=" + current_gene_name + "]");
答案 1 :(得分:35)
这是将鼠标悬停元素移动到前面的快速方法:
selection.on("mouseover", function() { this.parentNode.appendChild(this); });
另请参阅d3-js组中的related thread。
答案 2 :(得分:5)
有两种方法可以访问它
使用third variable就像这样:someNode.attr("someAttrib", function(d, i, j) { console.log(d, i, j); });
。 j
包含您提供给父节点的数据
或使用d3.select(this.parentNode).data()[0].id;
。
一个例子:
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<div id="area", width="1000px" height="1000px"></div>
<script>
var GAP = 10, NODE_RADIUS = 14;
var nodes = [
{id: 1, prop: [{id: 1, something: 1}], abc: 1},
{id: 2, prop: [{id: 1, something: 1}, {id: 2, something: 1}, {id: 3, something: 1}], abc: 2},
{id: 3, prop: [{id: 1, something: 1}, {id: 2, something: 1}], abc: 3},
{id: 4, prop: [{id: 1, something: 1}], abc: 4},
{id: 5, prop: [{id: 1, something: 1}], abc: 5},
{id: 6, prop: [], abc: 6}
];
var nodeLayer = d3.select("#area").selectAll(".node").data(nodes, function(d) {return d.id; });
var iNodes = nodeLayer.enter().append("svg").attr("class", "node");
//append the black circle
iNodes.append("circle")
.style("fill", "black")
.attr("r", NODE_RADIUS)
.attr("cx", function(d) {return 10 + d.id * 10;})
.attr("cy", 100);
iNodes.append("g").selectAll(".prop").data(function(d) {return d.prop;}).enter()
.append("text")
.text(function(d,i,j){console.log("parent id="+j); return d3.select(this.parentNode).data()[0].id;})
.attr("dx", 50)
.attr("dy", 50)
.style("font-size", "8px")
.style("fill", d3.rgb(180,0,0))
.style("text-anchor", "middle");
</script>
</body>
答案 3 :(得分:0)
由于某种原因,我不得不提高2倍的水平:console.log(">>"+my_chart.node().parentNode.parentNode.id+"<<")
答案 4 :(得分:0)
我做过的一种方法是:
bars.on('mouseover', d => {
let parentNode = d3.select(this.parentNode);
let tooltip = parentNode.append('rect)
从this
关键字可以访问当前节点,然后触摸其父节点。
答案 5 :(得分:0)
随着 D3 v4 的发布,这已成为一种 XY-problem。不再需要访问 parentNode
来重新插入元素作为其父元素的最后一个子元素。因为从 D3 上的那个版本开始提供 selection.raise()
方法:
选择.加注()
按顺序重新插入每个选定元素,作为其父元素的最后一个子元素。相当于:
selection.each(function() {
this.parentNode.appendChild(this);
});
使用 D3 v6,其中将事件作为第一个参数传递给事件侦听器(请参阅 changelog),您的代码可以像这样简单:
function onmouseover(event) {
d3.select(event.target).raise();
}
看看下面的演示:
d3.select("g")
.on("mouseover", event => d3.select(event.target).raise())
<script src="https://d3js.org/d3.v6.js"></script>
<svg width="400" height="400">
<g>
<rect x="100" y="50" width="100" height="100" fill="red"></rect>
<rect x="150" y="50" width="100" height="100" fill="blue"></rect>
</g>
</svg>