rgtk
rgtk

Reputation: 3510

Graph is not taking whole space in d3.js

I am trying to make simple line graph with d3.js but for reasons I cannot understand yet, the graph is not taking whole horizontal space. SVG element width inherits from parent <div> (200px) but path from d3.line() takes only 1/4 of total space.

Demo (fiddle)

<!DOCTYPE html>
<html>
  <head>
    <script src="https://d3js.org/d3.v4.min.js"></script>
  </head>
  <body>
    <div style="width: 200px;">
      <svg id="chart"></svg>
    </div>

    <script>
      let svg = document.getElementById('chart');
      let width = svg.parentElement.offsetWidth;
      let height = svg.parentElement.offsetHeight;
      let data = [23, 23, 42, 23, 21, 34, 45, 21, 23];

      let x = d3.scaleLinear()
          .domain([0, d3.max(data)])
          .range([0, width]);

      let y = d3.scaleLinear()
          .domain([0, d3.max(data)])
          .range([0, height]);

      let line = d3.line()
          .x((d, i) => x(i))
          .y((d, i) => y(d));

      let chart = d3.select('#chart')
          .attr('width', width)
          .attr('height', height);

      let path = chart.append('path')
          .attr('d', line(data))
          .attr('stroke', 'steelblue')
          .attr('stroke-width', 2)
          .attr('fill', 'none');
    </script>
  </body>
</html>

I believe this issue is strongly related with x axis scale function:

let x = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, width]);

But after many tries I couldn't figure it out.

Upvotes: 1

Views: 702

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102218

Since in the line generator you are passing the index of each data point to the x scale...

let line = d3.line()
    .x((d, i) => x(i))
    //index here---^

... the maximum value in the domain should be data.length - 1:

let x = d3.scaleLinear()
    .domain([0, data.length - 1])

Here is your code with that change:

svg {
  border: solid black 1px;
}
<script src="https://d3js.org/d3.v4.min.js"></script>
<div style="width: 200px;">
  <svg id="chart"></svg>
</div>
<script>
  let svg = document.getElementById('chart');
  let width = svg.parentElement.offsetWidth;
  let height = svg.parentElement.offsetHeight;
  let data = [23, 23, 42, 23, 21, 34, 45, 21, 23];

  let x = d3.scaleLinear()
    .domain([0, data.length - 1])
    .range([0, width]);

  let y = d3.scaleLinear()
    .domain([0, d3.max(data)])
    .range([0, height]);

  let line = d3.line()
    .x((d, i) => x(i))
    .y((d, i) => y(d));

  let chart = d3.select('#chart')
    .attr('width', width)
    .attr('height', height);

  let path = chart.append('path')
    .attr('d', line(data))
    .attr('stroke', 'steelblue')
    .attr('stroke-width', 2)
    .attr('fill', 'none');

</script>

PS: I put a border in the SVG just for you to see that now the line goes from one margin to other.

Upvotes: 2

Related Questions