Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3: How to refresh a chart with new data?

Tags:

d3.js

I have created a d3 donut chart. Here is my code:

var width = 480;
var height = 480;
var radius = Math.min(width, height) / 2;
var doughnutWidth = 30;

var color = d3.scale.category10();

var arc = d3.svg.arc()
.outerRadius(radius - 10)
.innerRadius(radius - 70);

var pie = d3.layout.pie()
.sort(null)
.value(function(d) { return d[1]; });

var dataset = settings.dataset;
console.log(dataset);

var svg = d3.select("body")
.append("svg")
.attr("width", width)
.attr("height", height)
.append("g")
.attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");

var path = svg.selectAll('path')
.data(pie(dataset))
.enter()
.append('path')
.attr('d', arc)
.attr('fill', function(d, i) { 
  return color(d.data[0]);
})

I have a simple form on my web page which displays a dropdown menu with several options. Every time a user changes a value on the form a new dataset is sent to my script (settings.dataset) and the donut is redrawn on the page.

Problem is, some of the values from the previous dataset remain in the DOM. In the console output below, you can see that the second dataset only has two elements. The third one is from the previous dataset. This is messing up the chart, as it is displaying a value that shouldn't be there.

enter image description here

My question: how do I clear the old values? I've read up on .exit() and .remove(), but I can't get my head around these methods.

like image 401
dbj44 Avatar asked Dec 04 '15 12:12

dbj44


People also ask

How do you clear a chart in Diablo 3?

clear() Function. The set. clear() function in D3. js is used to remove all values from the set.

What is enter () and exit () in D3 JS?

enter() function creates the initial join of the data with our DOM elements. Thus selecting only the elements that were not in the DOM yet. merge() function will select the DOM elements that did not exist in the DOM before and the ones that did. exit() function will select the DOM elements that are left from the join.

Is D3 good for data visualization?

D3 is often preferred over other data visualization tools as it is a very flexible tool that can provide dynamic properties to most of its functions.


3 Answers

Create one function that (re)draws the pie when it's created and when it's updated.

New data should be added to pie using enter() and old data should be removed using exit().remove()

It is as simple as this:

  path.enter().append("path")
            .attr("fill", function(d, i) { return color(i); })
            .attr("d", arc)
            .each(function(d) {this._current = d;} );

  path.transition()
            .attrTween("d", arcTween);

  path.exit().remove()

Full working code -> JSFIDDLE

like image 62
CuriousSuperhero Avatar answered Nov 03 '22 15:11

CuriousSuperhero


There are two steps to implement the 'redraw' effect you want:

First, I suppose you want the svg canvas to be drawn only once when the page is loaded for the first time, and then update the chart in the svg instead of remove and redraw the svg:

 var svg = d3.select("body")
              .selectAll("svg")
              .data([settings.dataset]);  
 // put data in an array with only one element

 // this ensures there is only one consistent svg on the page when data is updated(when the script gets executed) 
 svg.enter().append("svg")  

Second, understanding enter(), exit(), there are many great tutorials about this. In your case, I would suggest to draw the donut something like this:

var path = svg.selectAll(".donut")  
           .data(settings.data)

// bind data to elements, now you have elements belong to one of those 
// three 'states', enter, exit, or update

// for `enter` selection, append elements
path.enter().append("path").attr("d", arc).attr("fill", "teal")

// for `update` selection, which means they are already binded with data
path.transition().attrTween("d", someFunction) // apply transition here if you want some animation for data change

// for `exit` selection, they shouldn't be on the svg canvas since there is no corresponding data, you can then remove them
 path.exit().remove()
like image 10
fengshuo Avatar answered Nov 03 '22 15:11

fengshuo


//remove and create svg
d3.select("svg").remove(); 
var svg = d3.select("body").append("svg").attr("width","960").attr("height", "600"),
inner = svg.append("g");
like image 9
Kumar Vairakkannu Avatar answered Nov 03 '22 16:11

Kumar Vairakkannu