简体   繁体   中英

D3 v4 re-rendering nested objects, having problems with `enter()` and `exit()`

I'm trying to display a number of circles wrapped in <g> elements. This wrapping thing is important for me as in real world I want other elements to be in my group as well. The problem is, circles in the below example wont get displayed by first render(myObjects) call, and if you hit render button they are shown.

Second problem is when I press update the previously drawn circles are not removed and the new ones will render on top of them.

 var svg = d3.select('body').append('svg') .attr('width', 250) .attr('height', 250); //render the data function render(datum) { //Bind var groups = svg.selectAll("g").data(datum); groups.enter().append('g'); var circles = groups.append("circle").attr('r', 10) .attr('cx', function(d) { return dx; }) .attr('cy', function(d) { return dy; }); groups.exit().remove(); } var myObjects = [{ x: 100, y: 100 }, { x: 130, y: 120 }, { x: 80, y: 180 }, { x: 180, y: 80 }, { x: 180, y: 40 }]; var newObjects = [{ x: 200, y: 120 }, { x: 150, y: 160 }, { x: 20, y: 80 }, { x: 80, y: 60 }, { x: 100, y: 20 }]; function removeEls() { svg.selectAll('circle').remove(); } render(myObjects); 
 svg { width: 500px; height: 500px } button { float: left } text { text-anchor: middle; } circle { fill: orange; stroke: orange; fill-opacity: 0.5; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <button onclick="render(newObjects)">Update</button> <button onclick="render(myObjects);">Render</button> <button onclick="removeEls();">removeEls</button> 

You have 2 little issues in your code :

  1. You have added the circles in the groups instead of groups.enter() , hence the issue of not displaying the circles at the first draw
  2. You forget to add an identifier when you add the data, so the script is unable to detect which data is new and which data is not. I added a dx/dy identifier, which works in your case, but I advice you to add a true unique identifier. Like add a field id in your list of objects.

Here is the snippet with the corrections :

 var svg = d3.select('body').append('svg') .attr('width', 250) .attr('height', 250) .append('g'); //render the data function render(datum) { //Bind var groups = svg.selectAll("g").data(datum, d => (dx)/(dy)); var groupEnter = groups.enter().append('g'); var circles = groupEnter.append("circle").attr('r', 10) .attr('cx', function(d) { return dx; }) .attr('cy', function(d) { return dy; }); groups.exit().remove(); } var myObjects = [{ x: 100, y: 100 }, { x: 130, y: 120 }, { x: 80, y: 180},{ x: 180, y: 80 }, { x: 180, y: 40 }]; var newObjects = [{ x: 200, y: 120 }, { x: 150, y: 160 }, { x: 20, y: 80}, { x: 80, y: 60 }, { x: 100, y: 20 }]; function removeEls() { svg.selectAll('circle').remove(); } render(myObjects); 
 svg { width: 500px; height: 500px } button { float: left } text { text-anchor: middle; } circle { fill: orange; stroke: orange; fill-opacity: 0.5; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <button onclick="render(newObjects)">Update</button> <button onclick="render(myObjects);">Render</button> <button onclick="removeEls();">removeEls</button> 

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM