I've created the following document:
<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>
When I mouse over each path I want to append it last inside the svg:g
so it appears on top of the other lines, but I don't know how to properly select the 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
works, but I wanted to make sure that this
is a .line
, so I preferred to use current_gene_pcp
, but p2
returns <html></html>
as the parent, even though p3
returns the proper <g></g>
. This last version seems like a bug waiting to happen. Is there a better way?
A D3 selection is just a double-array wrapped around the element(s) selected. As you found with p3
, you can dereference the arrays to find your first node, if you want. However, a better method does exist:
From the docs for selection.node()
:
Returns the first non-
null
element in the current selection. If the selection is empty, returnsnull
.
In your case:
var dad = current_gene_pcp.node().parentNode;
However, if you don't need the line other than the DOM handle, you might as well just get that directly:
// 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 + "]");
Here's a quick way to move the mouseover element to the front:
selection.on("mouseover", function() { this.parentNode.appendChild(this); });
See also a related thread in the d3-js group.
There are two ways to access it.
Either use the third variable like this: someNode.attr("someAttrib", function(d, i, j) { console.log(d, i, j); });
. The j
contains the data you supplied to the parent node.
or use d3.select(this.parentNode).data()[0].id;
.
An example:
<!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>
出于某种原因,我不得不上升 2 console.log(">>"+my_chart.node().parentNode.parentNode.id+"<<")
: console.log(">>"+my_chart.node().parentNode.parentNode.id+"<<")
One way I have done is:
bars.on('mouseover', d => {
let parentNode = d3.select(this.parentNode);
let tooltip = parentNode.append('rect)
from this
key word, you can access the current node, then touch its parentNode.
With the release of D3 v4 this has become an XY-problem of sorts. There is no longer the need to get to the parentNode
to re-insert elements as the last child of its parent. Because from that release on D3 offers the selection.raise()
method:
selection . raise ()
Re-inserts each selected element, in order, as the last child of its parent. Equivalent to:
selection.each(function() { this.parentNode.appendChild(this); });
Using D3 v6 where the event is passed as the first parameter to the event listener (see changelog ) your code can be as simple as this:
function onmouseover(event) {
d3.select(event.target).raise();
}
Have a look at the following demo:
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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.