Reputation: 3510
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.
<!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
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