Search code examples
javascriptd3.jsjsfiddlescatter-plot

How to update the scattergraph?


I have this table and chart with scattergraph:

https://jsfiddle.net/horacebury/bygscx8b/6/

And I'm trying to update the positions of the scatter dots when the values in the second table column change.

Based on this SO I thought I could just use a single line (as I'm not changing the number of points, just their positions):

https://stackoverflow.com/a/16071155/71376

However, this code:

svg.selectAll("circle")
    .data(data)
    .transition()
    .duration(1000)
    .attr("cx", function(d) {
    return xScale(d[0]);
  })
    .attr("cy", function(d) {
    return yScale(d[1]);
  });

Is giving me this error:

Uncaught TypeError: svg.selectAll(...).data is not a function

Solution

  • The primary issue is that:

    svg.selectAll("circle") is not a typical selection as you have redefined svg to be a transition rather than a generic selection:

     var svg = d3.select("#chart").transition();
    

    Any selection using this svg variable will return a transition (from the API documentation), for example with transition.selectAll():

    For each selected element, selects all descendant elements that match the specified selector string, if any, and returns a transition on the resulting selection.

    For transitions, the .data method is not available.

    If you use d3.selectAll('circle') you will have more success. Alternatively, you could drop the .transition() when you define svg and apply it only to individual elements:

    var svg = d3.select('#chart');
    
    svg.select(".line").transition() 
      .duration(1000).attr("d", valueline(data));
    
    ...
    

    Here is an updated fiddle taking the latter approach.


    Also, for your update transition you might want to change scale and values you are using to get your new x,y values (to match your variable names):

        //Update all circles
        svg.selectAll("circle")
            .data(data)
            .transition()
            .duration(1000)
            .attr("cx", function(d) {
            return x(d.date);
          })
            .attr("cy", function(d) {
            return y(d.close);
          });
      }