d3多线图

时间:2016-12-01 18:47:47

标签: csv d3.js svg filtering

我有两个问题,我正在努力理解或解决我的以下d3代码(显示最简单的问题版本)。背景是我试图从csv文件绘制线条(在末尾粘贴的整个内容和在下面运行的完整代码)。前两行(用于说明csv的格式)是:

date,cust,prod,units
2012-04-01,team1,A,34

基本上有客户(team1,team2,team3)购买产品单元(A,B,C,D)。我正在尝试绘制按产品(A,B,C,D)过滤的折线图。这个单独工作。但是,由于每个产品(A,B,C,D)的单位和日期范围不同,我首先尝试将我的范围固定为最大日期范围和最大销售量。当我这样做时,轴看起来正确但图形不会被绘制。如果我只使用过滤后的数据,图表就可以正常工作。我错过了什么?我没有在控制台中看到任何JS错误。我的下一个目标是添加和删除图表(通过复选框)而无需重新绘制任何内容,最简单的方法是什么?

<!DOCTYPE html>
<meta charset="utf-8">
<style> /* set the CSS */

#line1 {
  fill: none;
  stroke: steelblue;
  stroke-width: 1px;
}

</style>

<div id="customer">

  <input class="custCB" type="checkbox" id="D_CB" name="cust" value="D" enabled onclick="showGraph('D')"> D<br>
  <input class="custCB" type="checkbox" id="C_cb" name="cust" value="C" enabled onclick="showGraph('C')"> C<br>
  <input class="custCB" type="checkbox" id="B_cb" name="cust" value="B" enabled onclick="showGraph('B')"> B<br>
  <input class="custCB" type="checkbox" id="A_cb" name="cust" value="A" enabled onclick="showGraph('A')"> A<br>
 </div>
<body>

<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
   showGraph("D");

   function showGraph(prod_name) {
    var mydomain = 5000;
    var margin = {top: 20, right: 20, bottom: 30, left: 50},
            width = 960 - margin.left - margin.right,
            height = 500 - margin.top - margin.bottom;
    // parse the date / time
    var parseTime = d3.timeParse("%Y-%m-%d");
    // set the ranges
    var x = d3.scaleTime().range([0, width]);
    var y = d3.scaleLinear().domain([mydomain, 0]).range([height, 0]);
    //console.log(y);
    // define the 1st line
    var valueline = d3.line()
            .x(function (d) {
                return x(d.date);
            })
            .y(function (d) {
                return y(d.units);
            });

    d3.select("svg").remove();
    var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom)
            .append("g")
            .attr("id", "parentgroup")
            .attr("transform",
            "translate(" + margin.left + "," + margin.top + ")");


    // Get the data
    d3.csv("test2.csv", function (error, tdata) {

        if (error) throw error;

        data = tdata.filter(e=> e.prod===prod_name);
        //_data = data.filter(e=> e.cust==="team2");
        //console.log("__data_", _data);
        // format the data
        console.log("data:", data);

        data.forEach(function (d) {
            d.date = parseTime(d.date);
            d.units = parseInt(d.units);
        });
        tdata.forEach(function (d) {
            d.date = parseTime(d.date);
            d.units = parseInt(d.units);
        });
        x.domain(d3.extent(tdata, function (d) {
            console.log(d.date);
            return d.date;
        }));
        //console.log("data", data);
        var m = d3.max(tdata, function (d) {
            console.log(d.units);
            var m = parseInt(d.units);
            return m;
        });
        console.log("Max:", m);
        y.domain([0, m]);
        console.log("tdata:", tdata);
        //console.log("data:", data);
        svg.append("path")
                .data([data])
                .attr("id", "line1")
                .attr("d", valueline);
        //console.log("DATA", data);
        svg.selectAll(".point")
                .data(data)
                .enter()
                .append("circle")
                .attr("class", "point")
                .attr("cx", function (d) {
                    return x(d.date);
                })
                .attr("cy", function (d) {
                    return y(d.units);
                })
                .attr("r", 4)
                .on("mouseover", function (d) {
                    console.log(d.units)
                });

        svg.append("g")
                .attr("id", "xaxis")
                .attr("transform", "translate(0," + height + ")")
                .call(d3.axisBottom(x));

        // Add the Y Axis
        svg.append("g")
                .attr("id", "yaxis")
                .call(d3.axisLeft(y));

    });
  }

</script>
</body>

 test2.csv
 date,cust,prod,units
 2012-04-01,team1,A,34
 2012-04-02,team1,B,45
 2012-04-03,team2,D,67
 2012-04-04,team1,A,78
 2012-04-05,team3,C,89
 2012-04-06,team2,D,99
 2012-04-07,team2,A,101
 2012-04-08,team3,A,122
 2012-04-09,team1,C,134
 2012-04-10,team1,C,160
 2012-04-11,team2,C,180
 2012-04-12,team2,D,210
 2012-04-13,team3,D,223 
 2012-04-14,team1,D,229
 2012-04-15,team1,D,241
 2012-04-16,team2,D,258
 2012-04-17,team2,C,350
 2012-04-18,team3,D,305
 2012-04-19,team3,B,335
 2012-04-20,team2,B,375
 2012-04-21,team3,D,345
 2012-04-22,team1,A,534
 2012-04-23,team1,C,578
 2012-04-24,team2,A,590
 2012-04-25,team1,B,601
 2012-04-26,team3,B,387
 2012-04-27,team2,C,613
 2012-04-28,team2,D,645
 2012-04-29,team3,D,410
 2012-04-30,team1,A,612
 2012-05-01,team2,A,670
 2012-05-02,team3,A,657
 2012-05-03,team1,A,690
 2012-05-04,team3,A,709
 2012-05-05,team2,C,690
 2012-05-06,team3,B,740
 2012-05-07,team1,A,1000

1 个答案:

答案 0 :(得分:1)

此代码段存在问题:

data.forEach(function (d) {
  d.date = parseTime(d.date);
  d.units = parseInt(d.units);
});
tdata.forEach(function (d) {
  d.date = parseTime(d.date);
  d.units = parseInt(d.units);
});

tdatadata是将引用保存到相同对象的数组。所以第二个forEach然后作用于相同的对象,parseTime失败。只是做:

tdata.forEach(function(d) {
  d.date = parseTime(d.date);
  d.units = parseInt(d.units);
});

var data = tdata.filter(e => e.prod === prod_name);

Here's your code all cleaned up.