D3.js streamgraph example - generating correct area function values

后端 未结 3 1353
无人共我
无人共我 2021-01-15 12:14

I\'m new to d3js and trying to adapt the streamgraph example from here http://bl.ocks.org/mbostock/4060954:

\"en

相关标签:
3条回答
  • 2021-01-15 12:23

    Just to note, there is a follow-up question here based on the same CSV data but attempting to use transitions. Similarly the error is related to 'area' but within the transition function.

    0 讨论(0)
  • 2021-01-15 12:28

    In your yDomain definition, you need to return the max of each layer's values, since each layer is a map - it has both a key and an array of values, rather than just a flat array of numbers.

    var yDomain = d3.max(layers0.concat(layers1), function(layer) { 
        return d3.max(layer.values, //Used to be layer
            function(d) { 
              return d.y0 + d.y; 
            }); 
    });
    

    Also, for your stack definition, you need to remove the second offset call.. it negates the "wiggle" one, so you will get a normal stacked graph rather than a streamgraph.

    stack = d3.layout.stack().offset("wiggle")  // Used to have .offset("zero") here
          .values(function(d) { return d.values; })
    

    Here's an example with both of those changed : http://jsfiddle.net/G6dTy/3/ . The numbers for the guestbook are small, and are dwarfed by the other two values.

    It might be informative to take a look at the Stacked area chart example

    0 讨论(0)
  • 2021-01-15 12:29

    Thanks minikomi! That was super helpful. The other thing I realized was off was that I wasn't parsing the x & y values into numbers and it was reading them as strings and making the points computation go crazy. So when it's iterating through the rows of the CSV file it needs to use parseInt:

    data.forEach(function(d) {
            d.date = format.parse(d.date);
            d.y = parseInt(d.num_visitors);
            d.x = parseInt(d.index);
    
        });
    

    Here are my updated files in case anyone wants to use this as an example in the future.

    HTML

    <!DOCTYPE html>
    <meta charset="utf-8">
    <title>Streamgraph</title>
    <script type="text/javascript" charset="utf-8" src="http://code.jquery.com/jquery-1.8.3.min.js"></script>
    <script src="bootstrap/js/bootstrap.min.js"></script>
    <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet">
    <style>
    
    body {
      font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
      margin: 0;
      position: relative;
      width: 1400px;
      background-color: #053749;
    }
    
    button {
      position: absolute;
      right: 10px;
      top: 10px;
    }
    svg{
      margin-top: 450px;
    }
    
    </style>
    <script src="d3.js"></script>
    <body>
      <div id="layerTitle"></div>
    </body>
    <script>
    
    
    var format = d3.time.format("%m/%d/%Y");
    
    d3.csv("streamdata.csv", function(error, data) {
            data.forEach(function(d) {
                d.date = format.parse(d.date);
                d.y = parseInt(d.num_visitors) + 1;
                d.x = parseInt(d.index);
    
            });
            window.data = data;
    
            drawVisitorStats();
            //$('path').tooltip('{container:layerTitle}');
            $("path").tooltip({
                'container': 'body',
                'placement': 'bottom'
            });
    
    
    });
    
    function drawVisitorStats(){
        var nest = d3.nest()
               .key(function(d){ return d.venue});
        var n = window.data.length, // number of layers, online, guestbook & museum
    
        stack = d3.layout.stack().offset("wiggle")
              .values(function(d) { return d.values; });
    
        //group data by venue
        layers0 = stack(nest.entries(data));
    
        var m = layers0[0].values.length; // number of samples per layer
    
        var allValues = layers0[0].values.concat(layers0[1].values).concat(layers0[2].values);
    
        var yDomain = d3.max(allValues, function(d) { 
          return d.y0 + d.y; 
        });
    
        var width = 1400,
            height = 200;
    
        var x = d3.scale.linear()
          .domain([0, m - 1])
          .range([0, width]);
    
        var y = d3.scale.linear()
        .domain([1, yDomain])
        .range([height, 0]);
    
        var color = d3.scale.linear()
            .range(["#053749", "#6bb9d6"]);
    
        var area = d3.svg.area()
          .x(
            function(d) { 
              return x(d.x); 
            })
            .y0(function(d) {          
              return y(d.y0); 
            })
            .y1(function(d) { 
              return y(d.y0 + d.y); 
            })
            .interpolate("cardinal")
            .tension(0.6); 
    
        var svg = d3.select("body").append("svg")
            .attr("width", width)
            .attr("height", height);
    
        svg.selectAll("path")
            .data(layers0)
          .enter().append("path")
            .attr("d", function(d) { return area(d.values); })
            .attr("id", function(d) { 
              return d.key;
            })
            .attr("title", function(d) { 
              return "visitors from " + d.key;
            })
            .style("fill", function() { return color(Math.random()); });
    }
    
    </script>
    </html>
    

    DATA FILE

    index,date,venue,num_visitors
    0,4/8/2013,online,1721
    0,4/8/2013,museum,826
    0,4/8/2013,guestbook,333
    1,4/9/2013,online,1377
    1,4/9/2013,museum,840
    1,4/9/2013,guestbook,61
    2,4/10/2013,online,1849
    2,4/10/2013,museum,539
    2,4/10/2013,guestbook,191
    3,4/11/2013,online,1205
    3,4/11/2013,museum,810
    3,4/11/2013,guestbook,65
    4,4/12/2013,online,1960
    4,4/12/2013,museum,957
    4,4/12/2013,guestbook,221
    5,4/13/2013,online,1215
    5,4/13/2013,museum,658
    5,4/13/2013,guestbook,384
    6,4/14/2013,online,1565
    6,4/14/2013,museum,621
    6,4/14/2013,guestbook,94
    7,4/15/2013,online,1678
    7,4/15/2013,museum,710
    7,4/15/2013,guestbook,35
    8,4/16/2013,online,1267
    8,4/16/2013,museum,964
    8,4/16/2013,guestbook,8
    9,4/17/2013,online,1781
    9,4/17/2013,museum,896
    9,4/17/2013,guestbook,238
    10,4/18/2013,online,1185
    10,4/18/2013,museum,712
    10,4/18/2013,guestbook,318
    11,4/19/2013,online,1097
    11,4/19/2013,museum,753
    11,4/19/2013,guestbook,132
    12,4/20/2013,online,1053
    12,4/20/2013,museum,927
    12,4/20/2013,guestbook,399
    13,4/21/2013,online,1738
    13,4/21/2013,museum,653
    13,4/21/2013,guestbook,78
    14,4/22/2013,online,1491
    14,4/22/2013,museum,568
    14,4/22/2013,guestbook,72
    15,4/23/2013,online,1403
    15,4/23/2013,museum,997
    15,4/23/2013,guestbook,184
    16,4/24/2013,online,1335
    16,4/24/2013,museum,987
    16,4/24/2013,guestbook,26
    17,4/25/2013,online,1964
    17,4/25/2013,museum,753
    17,4/25/2013,guestbook,239
    18,4/26/2013,online,1260
    18,4/26/2013,museum,815
    18,4/26/2013,guestbook,249
    19,4/27/2013,online,1404
    19,4/27/2013,museum,817
    19,4/27/2013,guestbook,360
    20,4/28/2013,online,1790
    20,4/28/2013,museum,840
    20,4/28/2013,guestbook,163
    21,4/29/2013,online,1698
    21,4/29/2013,museum,700
    21,4/29/2013,guestbook,129
    22,4/30/2013,online,1479
    22,4/30/2013,museum,921
    22,4/30/2013,guestbook,347
    23,5/1/2013,online,1093
    23,5/1/2013,museum,720
    23,5/1/2013,guestbook,278
    24,5/2/2013,online,1148
    24,5/2/2013,museum,655
    24,5/2/2013,guestbook,162
    25,5/3/2013,online,1521
    25,5/3/2013,museum,806
    25,5/3/2013,guestbook,267
    26,5/4/2013,online,1365
    26,5/4/2013,museum,662
    26,5/4/2013,guestbook,232
    27,5/5/2013,online,1809
    27,5/5/2013,museum,659
    27,5/5/2013,guestbook,398
    28,5/6/2013,online,1078
    28,5/6/2013,museum,999
    28,5/6/2013,guestbook,51
    29,5/7/2013,online,1477
    29,5/7/2013,museum,512
    29,5/7/2013,guestbook,385
    
    0 讨论(0)
提交回复
热议问题