D3 - 如何从对象数组创建多个折线图

D3 - How to create multiple line charts from an array of objects

我正在尝试从一组对象创建多个折线图,但很难理解如何绑定数据并正确创建 Y 轴和 X 轴。

以下是我正在处理的数据的简化版本:

var prices = [{
        "pagination": {
            "count": 6,
        },
        "data": [
            {
                "open": 9.67,
                "close": 9.98,
                "volume": 17876279,
                "symbol": "WISH",
                "date": "2021-08-05T00:00:00+0000"
            },
            {
                "open": 10.3,
                "close": 9.61,
                "volume": 34099145,
                "symbol": "WISH",
                "date": "2021-08-04T00:00:00+0000"
            },
            {
                "open": 10.36,
                "close": 10.31,
                "volume": 20379283,
                "symbol": "WISH",
                "date": "2021-08-03T00:00:00+0000"
            }
        ]
    },
    {
    "pagination": {
        "count": 6,
    },
    "data": [
        {
            "open": 27.3,
            "close": 28.33,
            "volume": 2360664,
            "symbol": "CRSR",
            "date": "2021-08-05T00:00:00+0000"
        },
        {
            "open": 26.83,
            "close": 27.4,
            "volume": 4409156,
            "symbol": "CRSR",
            "date": "2021-08-04T00:00:00+0000"
        },
        {
            "open": 26.99,
            "close": 27.13,
            "volume": 8675462,
            "symbol": "CRSR",
            "date": "2021-08-03T00:00:00+0000"
        }
    ]
}]

这就是我到目前为止在创建折线图时所做的工作

var priceMargin = {top: 10, right: 30, bottom: 30, left: 60},
    priceWidth = 460 - priceMargin.left - priceMargin.right,
    priceHeight = 400 - priceMargin.top - priceMargin.bottom;

var priceSvg = d3.selectAll(".company-price")
    .data(prices, function(d){
        return d.data
    })
    .append("svg")
        .attr("width", priceWidth + priceMargin.left + priceMargin.right)
        .attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
    .append("g")
        .attr("transform", "translate(" + priceMargin.left + "," + priceMargin.top + ")")

我的目标是为数组中的每个对象创建一个折线图,它由单独的“.company-price”中的 Y(收盘价)和 X(日期)轴的值范围组成 div 容器,但不确定如何创建 X 轴和 Y 轴并访问上面传入的数据。下面是我的 HTML 结构和我想要实现的目标的截图

如有任何帮助或建议,我们将不胜感激!

想想您在 d3 中创建的 div 数组。

const div = d3.select("#companies-container");

data.map(symbol=>{
  const {data, pagination} = symbol;

  const companyContainer = div.append("div").attr("class","company-container");
  const companyProfile = companyContainer.append("div").attr("class", "company-profile");
  const companyRecommend = companyContainer.append("div").attr("class", "company-container");
  const companyPrice = companyContainer.append("div").attr("class","company-price");

  const svg = companyPrice.append("svg").width(400).height(200);

  // All your code here

  const x = scaleLinear().domain(d3.extent(data, d=>d.date)).range([margin.left, width-margin.right]);

  // Calculate y, render lines etc.
})

在此处查看 JsFiddle https://jsfiddle.net/9ukd75yn/20/

这是实现此目的的一种方法,假设公司价格 div 已经创建并且与 prices 数组的顺序相同。

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <script src="https://d3js.org/d3.v7.js"></script>
</head>

<body>
  <div id="companies-container">
    <div id="company-container">
      <div class="company-price"></div>
    </div>
    <div id="company-container">
      <div class="company-price"></div>
    </div>
  </div>

  <script>
    // data
    const prices = [{
      "pagination": {
        "count": 6,
      },
      "data": [
        {
          "open": 9.67,
          "close": 9.98,
          "volume": 17876279,
          "symbol": "WISH",
          "date": "2021-08-05T00:00:00+0000"
        },
        {
          "open": 10.3,
          "close": 9.61,
          "volume": 34099145,
          "symbol": "WISH",
          "date": "2021-08-04T00:00:00+0000"
        },
        {
          "open": 10.36,
          "close": 10.31,
          "volume": 20379283,
          "symbol": "WISH",
          "date": "2021-08-03T00:00:00+0000"
        }
      ]
    },
    {
      "pagination": {
        "count": 6,
      },
      "data": [
        {
          "open": 27.3,
          "close": 28.33,
          "volume": 2360664,
          "symbol": "CRSR",
          "date": "2021-08-05T00:00:00+0000"
        },
        {
          "open": 26.83,
          "close": 27.4,
          "volume": 4409156,
          "symbol": "CRSR",
          "date": "2021-08-04T00:00:00+0000"
        },
        {
          "open": 26.99,
          "close": 27.13,
          "volume": 8675462,
          "symbol": "CRSR",
          "date": "2021-08-03T00:00:00+0000"
        }
      ]
    }];

    // bind the data to the company-price div
    // call the lineChart function for each div
    d3.selectAll('.company-price')
      .data(prices)
      .each(lineChart);

    // function to draw line chart
    function lineChart({pagination, data}) {
      const priceMargin = {top: 10, right: 30, bottom: 30, left: 60};
      const priceWidth = 460 - priceMargin.left - priceMargin.right;
      const priceHeight = 400 - priceMargin.top - priceMargin.bottom;

      // this refers to the company-price div
      const svg = d3.select(this)
        .append('svg')
          .attr("width", priceWidth + priceMargin.left + priceMargin.right)
          .attr("height", priceHeight + priceMargin.top + priceMargin.bottom)
        .append("g")
          .attr("transform", `translate(${priceMargin.left},${priceMargin.top})`);

      // scales

      const parseDate = d3.timeParse('%Y-%m-%dT%H:%M:%S%Z');

      const x = d3.scaleTime()
          .domain(d3.extent(data, d => parseDate(d.date)))
          .range([0, priceWidth]);

      const y = d3.scaleLinear()
          .domain(d3.extent(data, d => d.close))
          .range([priceHeight, 0]);

      // line generator

      const line = d3.line()
          .x(d => x(parseDate(d.date)))
          .y(d => y(d.close));

      // draw line

      svg.append('path')
          .attr('fill', 'none')
          .attr('stroke', 'steelblue')
          .attr('d', line(data));

      // axes

      svg.append('g')
          .call(d3.axisLeft(y));

      svg.append('g')
          .attr('transform', `translate(0,${priceHeight})`)
          .call(d3.axisBottom(x));
    }
  </script>
</body>

</html>