首页 > 解决方案 > 如何让线条在 d3.js 多折线图上呈现?

问题描述

我目前正在学习 d3,并且很难获得多折线图来呈现路径。在这种情况下,轴都是可见的,但是我无法弄清楚为什么实际的线条没有出现。我怀疑问题出在我对 scaleOrdinal 的使用(或误用)上。我已经成功地制作了具有相似数据的单折线图。

谁能帮我确定为什么我的行没有出现在这个例子中?

<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
        const width = 1000;
        const height = 500;
        const margin = 100;

        const data = [
            {"Name":"Argentina","Year":"2000","Spend":3266633317},
            {"Name":"Argentina","Year":"2001","Spend":3183591796},
            {"Name":"Argentina","Year":"2002","Spend":1114172483},
            {"Name":"Argentina","Year":"2003","Spend":1374873734},
            {"Name":"Argentina","Year":"2004","Spend":1465809188},
            {"Name":"Argentina","Year":"2005","Spend":1699579152},
            {"Name":"Argentina","Year":"2006","Spend":1847553130},
            {"Name":"Argentina","Year":"2007","Spend":2296448242},
            {"Name":"Argentina","Year":"2008","Spend":2788980205},
            {"Name":"Argentina","Year":"2009","Spend":2981852290},
            {"Name":"Argentina","Year":"2010","Spend":3475348407},
            {"Name":"Argentina","Year":"2011","Spend":4051930105},
            {"Name":"Argentina","Year":"2012","Spend":4563217859},
            {"Name":"Argentina","Year":"2013","Spend":5137974301},
            {"Name":"Argentina","Year":"2014","Spend":4979442724},
            {"Name":"Argentina","Year":"2015","Spend":5482616701},
            {"Name":"Argentina","Year":"2016","Spend":4509647660},
            {"Name":"Argentina","Year":"2017","Spend":5459643672},
            {"Name":"Argentina","Year":"2018","Spend":4144991771},
            {"Name":"Armenia","Year":"2000","Spend":68052142},
            {"Name":"Armenia","Year":"2001","Spend":66247626},
            {"Name":"Armenia","Year":"2002","Spend":64106406},
            {"Name":"Armenia","Year":"2003","Spend":76587999},
            {"Name":"Armenia","Year":"2004","Spend":98070488},
            {"Name":"Armenia","Year":"2005","Spend":140738103},
            {"Name":"Armenia","Year":"2006","Spend":188189116},
            {"Name":"Armenia","Year":"2007","Spend":280108688},
            {"Name":"Armenia","Year":"2008","Spend":395994365},
            {"Name":"Armenia","Year":"2009","Spend":359499344},
            {"Name":"Armenia","Year":"2010","Spend":395011508},
            {"Name":"Armenia","Year":"2011","Spend":390871434},
            {"Name":"Armenia","Year":"2012","Spend":380571679},
            {"Name":"Armenia","Year":"2013","Spend":444551860},
            {"Name":"Armenia","Year":"2014","Spend":457807022},
            {"Name":"Armenia","Year":"2015","Spend":447379808},
            {"Name":"Armenia","Year":"2016","Spend":431396219},
            {"Name":"Armenia","Year":"2017","Spend":443610413},
            {"Name":"Armenia","Year":"2018","Spend":608854650},
            {"Name":"Australia","Year":"2000","Spend":7273760313},
            {"Name":"Australia","Year":"2001","Spend":7043145895},
            {"Name":"Australia","Year":"2002","Spend":7946766202},
            {"Name":"Australia","Year":"2003","Spend":9926649415},
            {"Name":"Australia","Year":"2004","Spend":11995219710},
            {"Name":"Australia","Year":"2005","Spend":13237798499},
            {"Name":"Australia","Year":"2006","Spend":14239779513},
            {"Name":"Australia","Year":"2007","Spend":17186440962},
            {"Name":"Australia","Year":"2008","Spend":18633092318},
            {"Name":"Australia","Year":"2009","Spend":18960138513},
            {"Name":"Australia","Year":"2010","Spend":23217692816},
            {"Name":"Australia","Year":"2011","Spend":26597198655},
            {"Name":"Australia","Year":"2012","Spend":26216580848},
            {"Name":"Australia","Year":"2013","Spend":24825262589},
            {"Name":"Australia","Year":"2014","Spend":25783708714},
            {"Name":"Australia","Year":"2015","Spend":24045569111},
            {"Name":"Australia","Year":"2016","Spend":26382947050},
            {"Name":"Australia","Year":"2017","Spend":27691112417},
            {"Name":"Australia","Year":"2018","Spend":26711834225}
        ];

        const scaleX = d3
            .scaleLinear()
            .domain(d3.extent(data, d => d.Year))
            .range([margin, width - margin]);

        const scaleY = d3
            .scaleLinear()
            .domain(d3.extent(data, d => d.Spend))
            .range([height - margin, margin])
            .nice();

        const colorScale = d3
            .scaleOrdinal(d3.schemeCategory10)
            .domain(data.map(item => item.Name).reduce((a,b) => a.indexOf(b) !== -1 ? a : [...a, b], []));

        const line = d3
            .line()
            .x(d => scaleX(d.Year))
            .y(d => scaleY(d.Spend));

        const xAxis = d3.axisBottom(scaleX);

        const yAxis = d3.axisLeft(scaleY);

        const svg = d3
            .select("body")
            .append("svg")
            .attr("height", height)
            .attr("width", width);

        const axes = svg
            .append("g")
            .attr("class", "axes");

        axes.append("g")
            .call(xAxis)
            .attr("transform", `translate(${[0, height - margin]})`);

        axes.append("g")
            .call(yAxis)
            .attr("transform", `translate(${[margin, 0]})`);

        svg.selectAll("path.dataset")
            .data(data).join("path")
            .attr("class", "dataset")
            .attr("d", line)
            .attr("stroke", colorScale)
    </script>

标签: javascriptd3.js

解决方案


你的数据结构还没有准备好。你看,你正在处理每个对象,就好像它们是线生成器的可迭代对象,但显然它们不是。

一个简单的解决方案是按国家分组:

const groups = d3.groups(data, d => d.Name);

然后,只需执行以下操作:

svg.selectAll("path.dataset")
    .data(groups)
    .join("path")
    .attr("class", "dataset")
    .attr("d", d => line(d[1]))
    //etc...

这是您的代码进行了这 2 项更改:

path {
  fill: none;
}
<script src="https://d3js.org/d3.v6.min.js"></script>
<script>
  const width = 1000;
  const height = 500;
  const margin = 100;

  const data = [{
      "Name": "Argentina",
      "Year": "2000",
      "Spend": 3266633317
    },
    {
      "Name": "Argentina",
      "Year": "2001",
      "Spend": 3183591796
    },
    {
      "Name": "Argentina",
      "Year": "2002",
      "Spend": 1114172483
    },
    {
      "Name": "Argentina",
      "Year": "2003",
      "Spend": 1374873734
    },
    {
      "Name": "Argentina",
      "Year": "2004",
      "Spend": 1465809188
    },
    {
      "Name": "Argentina",
      "Year": "2005",
      "Spend": 1699579152
    },
    {
      "Name": "Argentina",
      "Year": "2006",
      "Spend": 1847553130
    },
    {
      "Name": "Argentina",
      "Year": "2007",
      "Spend": 2296448242
    },
    {
      "Name": "Argentina",
      "Year": "2008",
      "Spend": 2788980205
    },
    {
      "Name": "Argentina",
      "Year": "2009",
      "Spend": 2981852290
    },
    {
      "Name": "Argentina",
      "Year": "2010",
      "Spend": 3475348407
    },
    {
      "Name": "Argentina",
      "Year": "2011",
      "Spend": 4051930105
    },
    {
      "Name": "Argentina",
      "Year": "2012",
      "Spend": 4563217859
    },
    {
      "Name": "Argentina",
      "Year": "2013",
      "Spend": 5137974301
    },
    {
      "Name": "Argentina",
      "Year": "2014",
      "Spend": 4979442724
    },
    {
      "Name": "Argentina",
      "Year": "2015",
      "Spend": 5482616701
    },
    {
      "Name": "Argentina",
      "Year": "2016",
      "Spend": 4509647660
    },
    {
      "Name": "Argentina",
      "Year": "2017",
      "Spend": 5459643672
    },
    {
      "Name": "Argentina",
      "Year": "2018",
      "Spend": 4144991771
    },
    {
      "Name": "Armenia",
      "Year": "2000",
      "Spend": 68052142
    },
    {
      "Name": "Armenia",
      "Year": "2001",
      "Spend": 66247626
    },
    {
      "Name": "Armenia",
      "Year": "2002",
      "Spend": 64106406
    },
    {
      "Name": "Armenia",
      "Year": "2003",
      "Spend": 76587999
    },
    {
      "Name": "Armenia",
      "Year": "2004",
      "Spend": 98070488
    },
    {
      "Name": "Armenia",
      "Year": "2005",
      "Spend": 140738103
    },
    {
      "Name": "Armenia",
      "Year": "2006",
      "Spend": 188189116
    },
    {
      "Name": "Armenia",
      "Year": "2007",
      "Spend": 280108688
    },
    {
      "Name": "Armenia",
      "Year": "2008",
      "Spend": 395994365
    },
    {
      "Name": "Armenia",
      "Year": "2009",
      "Spend": 359499344
    },
    {
      "Name": "Armenia",
      "Year": "2010",
      "Spend": 395011508
    },
    {
      "Name": "Armenia",
      "Year": "2011",
      "Spend": 390871434
    },
    {
      "Name": "Armenia",
      "Year": "2012",
      "Spend": 380571679
    },
    {
      "Name": "Armenia",
      "Year": "2013",
      "Spend": 444551860
    },
    {
      "Name": "Armenia",
      "Year": "2014",
      "Spend": 457807022
    },
    {
      "Name": "Armenia",
      "Year": "2015",
      "Spend": 447379808
    },
    {
      "Name": "Armenia",
      "Year": "2016",
      "Spend": 431396219
    },
    {
      "Name": "Armenia",
      "Year": "2017",
      "Spend": 443610413
    },
    {
      "Name": "Armenia",
      "Year": "2018",
      "Spend": 608854650
    },
    {
      "Name": "Australia",
      "Year": "2000",
      "Spend": 7273760313
    },
    {
      "Name": "Australia",
      "Year": "2001",
      "Spend": 7043145895
    },
    {
      "Name": "Australia",
      "Year": "2002",
      "Spend": 7946766202
    },
    {
      "Name": "Australia",
      "Year": "2003",
      "Spend": 9926649415
    },
    {
      "Name": "Australia",
      "Year": "2004",
      "Spend": 11995219710
    },
    {
      "Name": "Australia",
      "Year": "2005",
      "Spend": 13237798499
    },
    {
      "Name": "Australia",
      "Year": "2006",
      "Spend": 14239779513
    },
    {
      "Name": "Australia",
      "Year": "2007",
      "Spend": 17186440962
    },
    {
      "Name": "Australia",
      "Year": "2008",
      "Spend": 18633092318
    },
    {
      "Name": "Australia",
      "Year": "2009",
      "Spend": 18960138513
    },
    {
      "Name": "Australia",
      "Year": "2010",
      "Spend": 23217692816
    },
    {
      "Name": "Australia",
      "Year": "2011",
      "Spend": 26597198655
    },
    {
      "Name": "Australia",
      "Year": "2012",
      "Spend": 26216580848
    },
    {
      "Name": "Australia",
      "Year": "2013",
      "Spend": 24825262589
    },
    {
      "Name": "Australia",
      "Year": "2014",
      "Spend": 25783708714
    },
    {
      "Name": "Australia",
      "Year": "2015",
      "Spend": 24045569111
    },
    {
      "Name": "Australia",
      "Year": "2016",
      "Spend": 26382947050
    },
    {
      "Name": "Australia",
      "Year": "2017",
      "Spend": 27691112417
    },
    {
      "Name": "Australia",
      "Year": "2018",
      "Spend": 26711834225
    }
  ];

  const groups = d3.groups(data, d => d.Name);

  const scaleX = d3
    .scaleLinear()
    .domain(d3.extent(data, d => d.Year))
    .range([margin, width - margin]);

  const scaleY = d3
    .scaleLinear()
    .domain(d3.extent(data, d => d.Spend))
    .range([height - margin, margin])
    .nice();

  const colorScale = d3
    .scaleOrdinal(d3.schemeCategory10)
    .domain(data.map(item => item.Name).reduce((a, b) => a.indexOf(b) !== -1 ? a : [...a, b], []));

  const line = d3
    .line()
    .x(d => scaleX(d.Year))
    .y(d => scaleY(d.Spend));

  const xAxis = d3.axisBottom(scaleX);

  const yAxis = d3.axisLeft(scaleY);

  const svg = d3
    .select("body")
    .append("svg")
    .attr("height", height)
    .attr("width", width);

  const axes = svg
    .append("g")
    .attr("class", "axes");

  axes.append("g")
    .call(xAxis)
    .attr("transform", `translate(${[0, height - margin]})`);

  axes.append("g")
    .call(yAxis)
    .attr("transform", `translate(${[margin, 0]})`);

  svg.selectAll("path.dataset")
    .data(groups)
    .join("path")
    .attr("class", "dataset")
    .attr("d", d => line(d[1]))
    .attr("stroke", colorScale)
</script>


推荐阅读