将迷你图添加到嵌套JSON数据生成的d3.js表中

时间:2015-11-16 05:25:12

标签: javascript json d3.js

我正在从JSON文件构建表。该表有多个列,其中包含不同年份的值。我希望最后一栏成为一个显示趋势的迷你线。我有代码工作的表。我有代码工作的迷你线。但我无法为我的生活获得出现在桌面内的迷你线。

我在StackOverflow上发现了类似的问题,它有一个很好的答案: Inline D3 sparklines in a table alongside text

不幸的是,我无法理解如何以这种方式获取数据。非常感谢任何帮助。

代码在下面,并且是here as a plunker

    <!DOCTYPE html>
    <html>
    <head>
        <style>
            body{
                font-family:Arial, sans-serif;
                font-size:14px;
            }
            table{
                border-spacing:0;
                padding:0;
            }
            th{
              text-align:left;
              font-weight:normal !important;
              border-top:1px solid #ddd;
              border-left:1px solid #ddd;
              border-bottom:1px solid #ddd;
                height:25px;
                padding-left:5px;
                width: 50px;
            }
            td{
              border:1px solid #ddd;
                width:30px !important;
                height:25px;
                padding-left:5px;
            }
            tr.row-odd,
            .row-odd{
                background: #eee;
            }
            #sparks{
                float:left;
                width:20%;
            }
            .sparkline{
                height:25px;
                width:200px;
            }
            .Sparkline{
                width:200px !important;
            }
        </style>
        <script src="http://d3js.org/d3.v3.min.js"></script>
        <script src="//code.jquery.com/jquery-1.10.2.js"></script>

    </head>
    <body>
        <div id="indcontent">
        </div>
        <div id="sparks"></div>

    <script>

    var data;

    d3.json("data.json", function(json) {

                jsonData = json;

                json.forEach(function(d) {
                  d.value = Math.round((+d.value + 0.00001) * 1000) / 1000;
                  d.year = +d.year;
                });

                // add years for select indicator
                var nestyr = d3.nest()      
                    .key(function(d) { return d.year; })
                    .sortKeys(d3.ascending)
                    .map(json);

                var yearstring = Object.keys(nestyr);

                // //////////////////////////
                var width = 200, height = 25;
                var graph = d3.select("#sparks")
                var minInd = d3.min(json, function(d) { return d.value;} )
                var maxInd = d3.max(json, function(d) { return d.value;} )

                xScale = d3.scale.linear().range([0, width - 10]).domain(d3.extent(json, function(d) { return d.year; })),  
                yScale = d3.scale.linear().range([height, 0]).domain([minInd,maxInd]),

                xAxis = d3.svg.axis().scale(xScale).tickFormat(d3.format('0f')),
                yAxis = d3.svg.axis().scale(yScale).orient("left");

                var type = d3.nest()
                      .key(function(d) { return d.state; })
                        .sortKeys(d3.ascending)
                      .entries(json);

                var line = d3.svg.line()
                    .x(function(d){return xScale(d.year);})
                    .y(function(d){return yScale(d.value);});


                    // this adds the sparklines below the chart, where they are showing up now.
                    var indi = graph.selectAll("svg")
                        .data(type)
                        .enter().append("svg")
                            .attr("class", function(d, i){ 
                                if (i++ % 2 === 0){return 'row-even sparkline ' + d.key}
                                else {return 'row-odd sparkline ' + d.key}});

                    indi.append("path")
                    .attr("d", function(d){ d.line = this; return line(d.values); })
                    .attr("stroke-width", 1)
                    .attr("stroke", "#c00000")
                    .attr("fill", "none");



            var tableData = [],
                states = {};
                json.forEach(function (d) {
                var state = states[d.state];
                if (!state) {
                    tableData.push(state = states[d.state] = {});
                    }
                state[d.year] = d.value,
                states[d.state].State = d.state;
            });

            console.log("tableData", tableData)

            yearstring.unshift("State");
            yearstring.push("Sparkline");

            updateGraph(data);

            // render the table(s)
            tabulate(tableData, yearstring);

    }); // close json


    function updateGraph(data) {

    // add years for select indicator
        var nestyr = d3.nest()      
                .key(function(d) { return d.year; })
                .sortKeys(d3.ascending)
                .map(jsonData);

        var yearstring = Object.keys(nestyr);           

        minyear = d3.min(yearstring);
        maxyear = d3.max(yearstring);                                                           

    };

    function tabulate(newData, columns) {

                var type = d3.nest()
              .key(function(d) { return d.state; })
                .sortKeys(d3.ascending)
              .entries(jsonData);

                var table = d3.select('#indcontent').append('table')
                var thead = table.append('thead')
                var tbody = table.append('tbody');

                // append the header row
                thead.append('tr')
                  .selectAll('th')
                  .data(columns).enter()
                  .append('th')
                    .text(function (column) { return column; });

                // create a row for each object in the data
                var rows = tbody.selectAll('tr')
                  .data(newData)
                  .enter()
                  .append('tr');

                  // add stripes to the table
                rows.attr("class", function(d, i){ if (i++ % 2 === 0){return 'row-even'}else {return 'row-odd'}});


                // create a cell in each row for each column
                var cells = rows.selectAll('td')
                  .data(function (row) {
                    return columns.map(function (column) {
                      return {column: column, value: row[column]};
                    });                 
                  })
                  .enter()
                  .append('td')
                        .attr("class", function (d,i) { return columns[i]; })
                    .html(function (d) { return d.value; });

                        // Here's where I'm attempting to add the sparklines inside the table cells. This isn't doing anything right now.
                        rows.selectAll("td.Sparkline")
                                                .data(function(d,i){type[i]})
                                                .enter()
                                    .append("svg")
                                    .attr("class", "spark")
                                                .attr("height", 25)
                                                .attr("width", 200);

                                                var isit = d3.selectAll(".spark")
                                                .append("path")
                                                .attr("d", function(d){ d.line = this; return line(d.values); })
                                                .attr("stroke-width", 1)
                                                .attr("stroke", "#c00000")
                                                .attr("fill", "none");

              return table;
    };
    </script>
    </body>
    </html>

1 个答案:

答案 0 :(得分:1)

我在您的代码中发现的小错误如下。

  • 您错过了数据绑定函数中的return语句,返回类型是一个对象而不是数组。
  • 新的svg元素被附加到行而不是td元素。
  • 变量line超出了范围。它应该在外面宣布。

创建火花线,如下所示。

代码:

rows.selectAll("td.Sparkline")
    .selectAll(".spark")
    .data(function(d,i){ return [type[i]] })
    .enter()
    .append("svg")
    .attr("class", "spark")
    .attr("height", 25)
    .attr("width", 200)
    .append("path")
    .attr("d", function(d,i){ d.line = this; return line(d.values); });
    .attr("stroke-width", 1)
    .attr("stroke", "#c00000")
    .attr("fill", "none");

var json = [{
  "state": "Alabama",
  "value": 2,
  "year": 2003
}, {
  "state": "Alabama",
  "value": 0,
  "year": 2004
}, {
  "state": "Alabama",
  "value": 6,
  "year": 2005
}, {
  "state": "Alabama",
  "value": 2,
  "year": 2006
}, {
  "state": "Alabama",
  "value": 4,
  "year": 2007
}, {
  "state": "Alabama",
  "value": 4,
  "year": 2008
}, {
  "state": "Alaska",
  "value": 0,
  "year": 2003
}, {
  "state": "Alaska",
  "value": 1,
  "year": 2004
}, {
  "state": "Alaska",
  "value": 2,
  "year": 2005
}, {
  "state": "Alaska",
  "value": 1,
  "year": 2006
}, {
  "state": "Alaska",
  "value": 2,
  "year": 2007
}, {
  "state": "Alaska",
  "value": 5,
  "year": 2008
}, {
  "state": "Arizona",
  "value": 6,
  "year": 2003
}, {
  "state": "Arizona",
  "value": 4,
  "year": 2004
}, {
  "state": "Arizona",
  "value": 5,
  "year": 2005
}, {
  "state": "Arizona",
  "value": 7,
  "year": 2006
}, {
  "state": "Arizona",
  "value": 3,
  "year": 2007
}, {
  "state": "Arizona",
  "value": 8,
  "year": 2008
}, {
  "state": "Arkansas",
  "value": null,
  "year": 2003
}, {
  "state": "Arkansas",
  "value": 0,
  "year": 2004
}, {
  "state": "Arkansas",
  "value": 1,
  "year": 2005
}, {
  "state": "Arkansas",
  "value": 3,
  "year": 2006
}, {
  "state": "Arkansas",
  "value": 1,
  "year": 2007
}, {
  "state": "Arkansas",
  "value": null,
  "year": 2008
}, {
  "state": "California",
  "value": 10,
  "year": 2003
}, {
  "state": "California",
  "value": 12,
  "year": 2004
}, {
  "state": "California",
  "value": 9,
  "year": 2005
}, {
  "state": "California",
  "value": 5,
  "year": 2006
}, {
  "state": "California",
  "value": 8,
  "year": 2007
}, {
  "state": "California",
  "value": 3,
  "year": 2008
}, {
  "state": "Colorado",
  "value": 2,
  "year": 2003
}, {
  "state": "Colorado",
  "value": 12,
  "year": 2004
}, {
  "state": "Colorado",
  "value": 12,
  "year": 2005
}, {
  "state": "Colorado",
  "value": 11,
  "year": 2006
}, {
  "state": "Colorado",
  "value": 7,
  "year": 2007
}, {
  "state": "Colorado",
  "value": 2,
  "year": 2008
}, {
  "state": "Connecticut",
  "value": 0,
  "year": 2003
}, {
  "state": "Connecticut",
  "value": 5,
  "year": 2004
}, {
  "state": "Connecticut",
  "value": 4,
  "year": 2005
}, {
  "state": "Connecticut",
  "value": 4,
  "year": 2006
}, {
  "state": "Connecticut",
  "value": 3,
  "year": 2007
}, {
  "state": "Connecticut",
  "value": 5,
  "year": 2008
}, {
  "state": "Delaware",
  "value": 1,
  "year": 2003
}, {
  "state": "Delaware",
  "value": 1,
  "year": 2004
}, {
  "state": "Delaware",
  "value": 1,
  "year": 2005
}, {
  "state": "Delaware",
  "value": 5,
  "year": 2006
}, {
  "state": "Delaware",
  "value": 2,
  "year": 2007
}, {
  "state": "Delaware",
  "value": 4,
  "year": 2008
}];
var data, line;

//d3.json("data.json", function(json) {

jsonData = json;

json.forEach(function(d) {
  d.value = Math.round((+d.value + 0.00001) * 1000) / 1000;
  d.year = +d.year;
});

// add years for select indicator
var nestyr = d3.nest()
  .key(function(d) {
    return d.year;
  })
  .sortKeys(d3.ascending)
  .map(json);

var yearstring = Object.keys(nestyr);

// //////////////////////////
var width = 200,
  height = 25;
var graph = d3.select("#sparks")
var minInd = d3.min(json, function(d) {
  return d.value;
})
var maxInd = d3.max(json, function(d) {
  return d.value;
})

xScale = d3.scale.linear().range([0, width - 10]).domain(d3.extent(json, function(d) {
    return d.year;
  })),
  yScale = d3.scale.linear().range([height, 0]).domain([minInd, maxInd]),

  xAxis = d3.svg.axis().scale(xScale).tickFormat(d3.format('0f')),
  yAxis = d3.svg.axis().scale(yScale).orient("left");

var type = d3.nest()
  .key(function(d) {
    return d.state;
  })
  .sortKeys(d3.ascending)
  .entries(json);

line = d3.svg.line()
  .x(function(d) {
    return xScale(d.year);
  })
  .y(function(d) {
    return yScale(d.value);
  });

// this adds the sparklines below the chart, where they are showing up now.
var indi = graph.selectAll("svg")
  .data(type)
  .enter().append("svg")
  .attr("class", function(d, i) {
    if (i++ % 2 === 0) {
      return 'row-even sparkline ' + d.key
    } else {
      return 'row-odd sparkline ' + d.key
    }
  });

indi.append("path")
  .attr("d", function(d) {
    d.line = this;
    return line(d.values);
  })
  .attr("stroke-width", 1)
  .attr("stroke", "#c00000")
  .attr("fill", "none");



var tableData = [],
  states = {};
json.forEach(function(d) {
  var state = states[d.state];
  if (!state) {
    tableData.push(state = states[d.state] = {});
  }
  state[d.year] = d.value,
    states[d.state].State = d.state;
});

console.log("tableData", tableData)

yearstring.unshift("State");
yearstring.push("Sparkline");

updateGraph(data);

// render the table(s)
tabulate(tableData, yearstring);

//}); // close json


function updateGraph(data) {

  // add years for select indicator
  var nestyr = d3.nest()
    .key(function(d) {
      return d.year;
    })
    .sortKeys(d3.ascending)
    .map(jsonData);

  var yearstring = Object.keys(nestyr);

  minyear = d3.min(yearstring);
  maxyear = d3.max(yearstring);

};

function tabulate(newData, columns) {

  var type = d3.nest()
    .key(function(d) {
      return d.state;
    })
    .sortKeys(d3.ascending)
    .entries(jsonData);

  var table = d3.select('#indcontent').append('table')
  var thead = table.append('thead')
  var tbody = table.append('tbody');

  // append the header row
  thead.append('tr')
    .selectAll('th')
    .data(columns).enter()
    .append('th')
    .text(function(column) {
      return column;
    });

  // create a row for each object in the data
  var rows = tbody.selectAll('tr')
    .data(newData)
    .enter()
    .append('tr');

  // add stripes to the table
  rows.attr("class", function(d, i) {
    if (i++ % 2 === 0) {
      return 'row-even'
    } else {
      return 'row-odd'
    }
  });


  // create a cell in each row for each column
  var cells = rows.selectAll('td')
    .data(function(row) {
      return columns.map(function(column) {
        return {
          column: column,
          value: row[column]
        };
      });
    })
    .enter()
    .append('td')
    .attr("class", function(d, i) {
      return columns[i];
    })
    .html(function(d) {
      return d.value;
    });

  // Here's where I'm attempting to add the sparklines inside the table cells. This isn't doing anything right now.
  rows.selectAll("td.Sparkline")
    .selectAll(".spark")
    .data(function(d, i) {
      return [type[i]]
    })
    .enter()
    .append("svg")
    .attr("class", "spark")
    .attr("height", 25)
    .attr("width", 200)
    .append("path")
    .attr("d", function(d, i) {
      d.line = this;
      return line(d.values);
    })
    .attr("stroke-width", 1)
    .attr("stroke", "#c00000")
    .attr("fill", "none");

  return table;
};
body {
  font-family: Arial, sans-serif;
  font-size: 14px;
}
table {
  border-spacing: 0;
  padding: 0;
}
th {
  text-align: left;
  font-weight: normal !important;
  border-top: 1px solid #ddd;
  border-left: 1px solid #ddd;
  border-bottom: 1px solid #ddd;
  height: 25px;
  padding-left: 5px;
  width: 50px;
}
td {
  border: 1px solid #ddd;
  width: 30px !important;
  height: 25px;
  padding-left: 5px;
}
tr.row-odd,
.row-odd {
  background: #eee;
}
#sparks {
  float: left;
  width: 20%;
}
.sparkline {
  height: 25px;
  width: 200px;
}
.Sparkline {
  width: 200px !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<div id="indcontent">
</div>
<div id="sparks"></div>