How can I bring the circle forward with d3?

First of all, I use d3.js to display circles of different sizes in arrays. Hover over the drawer, I want the circle to be aligned to become larger, which I can do, but I have no idea how to move it to the front. Currently, when he is displayed, he is hiding behind several other circles. How can i fix this?

Here is a sample code:

.on("mouseover", function() { d3.select(this).attr("r", function(d) { return 100; }) }) 

I tried using the sort and order methods, but they did not work. I am pretty sure I did not do it right. Any thoughts?

+62
javascript visualization
Jan 05 '13 at 2:14
source share
4 answers

You will need to reorder the object and make the circle you hover over the last element added. As you can see here: https://gist.github.com/3922684 and, as suggested by nautat , you should define the following before your main script:

 d3.selection.prototype.moveToFront = function() { return this.each(function(){ this.parentNode.appendChild(this); }); }; 

Then you just need to call the moveToFront function on your object (say circles ) when you hover over the mouse:

 circles.on("mouseover",function(){ var sel = d3.select(this); sel.moveToFront(); }); 

Edit: As suggested by Henrik Nordberg , you need to bind data to the DOM using the second .data() argument. This is necessary so as not to lose the binding to the elements. Please read Henrik's answer (and upgrade it!) For more information. As a general tip, always use the second .data() argument when binding data to the DOM to take advantage of the full d3 performance.




Edit: As Clemens Tolboom mentioned, the inverse function would be:

 d3.selection.prototype.moveToBack = function() { this.each(function() { this.parentNode.firstChild && this.parentNode.insertBefore(this, firstChild); } }); }; 
+117
Jan 20 '13 at 16:18
source share

If you use the moveToFront() method, make sure that you specify the second argument to the data() join method or that your data will not be synchronized with your DOM.

d3.js combines your data (provided by parse() ) with the generated DOM elements. If you manipulate the DOM as suggested above, d3.js will not know which DOM element corresponds to which data point, unless you specify a unique value for each data point in the data() call as an API reference shows:

.data(data, function(d) { return d.name; })

+22
Apr 04 '13 at 17:14
source share

In version d3 version 4, there is a set of built-in functions that process this type of behavior without the need to implement it yourself. See the d3v4 documentation for more information.

In short, to bring an element forward, use selection.raise()

selection.raise ()

Inserts each selected item in order, as the last child of its parent. Equivalent to:

selection.each(function() {
this.parentNode.appendChild(this);
});

+18
Mar 08 '17 at 13:52 on
source share

From my excruciating experience with IE9, using parentNode.appendChild can result in loss of event handlers in the nodes. Therefore, I tend to use a different approach, i.e. sorting the nodes so that the selected one is higher than the others:

  .on("mouseover", function(selected) { vis.selectAll('.node') .sort(function(a, b) { if (a.id === selected.id) { return 1; } else { if (b.id === selected.id) { return -1; } else { return 0; } } }); }) 
+13
Dec 06 '13 at 14:24
source share



All Articles