0

I am trying to create multiple line charts from an array of objects but having difficulty of understanding how to bind the data and create the Y and X axes correctly.

Below is a shortened version of the data that I am working with:

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"
        }
    ]
}]

And this is what I have done so far in creating the line charts

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 + ")")

My goal is to create a line chart for every object inside the array that consists of its own range of values for the Y(close) and X(dates) axes inside separate ".company-price" div container, but not sure how create the X-axis and Y-axis and access the data that was passed in above. Below is a screenshot of my HTML structure and the goal I would like to achieve

HTML structure

Goal

Any help or advice would be greatly appreciated!

2 Answers 2

1

Here is one way to achieve this, assuming the company-price divs are already created and are in the same order as the prices array.

<!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>

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Dan once again your answer is super helpful and achieved what I am looking for
0

Think of an array of divs which you create in d3.

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.
})

See the JsFiddle here https://jsfiddle.net/9ukd75yn/20/

4 Comments

Hi, thank you for responding to my question. One thing I forgot to add was for each of the line chart, I want to to create it in a separate container of div. Please see my edited post for screenshot of the HTML structure. The above approach you suggested seems to create all line charts within a single container
yes, it does.. what you can do is create divs also within d3. Have edited my answer.
Thanks for getting back. Your suggested approach seems to append multiple ".company-price" divs under each ".company-container". Please have a look at my HTML structure that I already created the ".company-price" div and I would like to append a line graph into each of the div that is already there. I added a visual picture of the goal I want to achieve
Please see the structure generated by this fiddle here jsfiddle.net/9ukd75yn/20 Is this what you wish to achieve?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.