Emile
Emile

Reputation: 197

D3 scatter plot y-axis numbers display incomplete

I am new to D3 and I am making a scatter plot with it. Here's the code:

var dataset = [[5, 20], [480, 90], [250, 50], [100, 33], [330, 95],[410, 12], [475, 44], [25, 67], [85, 21], [220, 88]];
var margin = {top: 20, right: 20, bottom: 20, left: 20},
    width = +400 - margin.left - margin.right,
    height = +400 - margin.top - margin.bottom

var svg = d3.select("svg");
var xScale = d3.scaleLinear()
               .domain([0, d3.max(dataset, function(d) { return d[0]})])
               .range([20, 380]);
var yScale = d3.scaleLinear()
               .domain([0, d3.max(dataset, function(d) { return d[1]})])
               .range([380, 20]);
svg.selectAll("circle") 
   .data(dataset)  
   .enter().append("circle")
   .attr("cx", function(d) {return xScale(d[0]); })  
   .attr("cy", function(d) {return yScale(d[1]); }) 
   .attr("r", 5);

var yAxis = d3.axisLeft()
              .scale(yScale)
              .ticks(10);
svg.append("g")
   .attr("class","axis")
   .attr("transform", "translate(" + margin.left + " ,0)")
   .call(yAxis);

And I got:

enter image description here

So the numbers on the y-axis is blocked because there is not enough left margin space. I know I can change the font size but are there any other ways to solve this problem? I tried to change the left margin value but it just became a mess. Thanks in advance!

Upvotes: 1

Views: 398

Answers (1)

Gerardo Furtado
Gerardo Furtado

Reputation: 102174

Right now, your ranges are hardcoded:

var xScale = d3.scaleLinear()
    .range([20, 380]);

var yScale = d3.scaleLinear()
    .range([380, 20]);

Therefore, any change you make on the margin object has no effect in the dots.

Solution: Use the margin object to set the ranges:

var xScale = d3.scaleLinear()
    .range([margin.left, width - margin.right]);

var yScale = d3.scaleLinear()
    .range([height - margin.bottom, margin.top]);

That way, the chart dynamically adapts to any change you make on the margins. Here is a demo, with margin.left: 50:

var dataset = [
    [5, 20],
    [480, 90],
    [250, 50],
    [100, 33],
    [330, 95],
    [410, 12],
    [475, 44],
    [25, 67],
    [85, 21],
    [220, 88]
];
var margin = {
        top: 20,
        right: 20,
        bottom: 20,
        left: 50
    },
    width = 400,
    height = 400;

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

var xScale = d3.scaleLinear()
    .domain([0, d3.max(dataset, function(d) {
        return d[0]
    })])
    .range([margin.left, width - margin.right]);
var yScale = d3.scaleLinear()
    .domain([0, d3.max(dataset, function(d) {
        return d[1]
    })])
    .range([height - margin.bottom, margin.top]);
svg.selectAll("circle")
    .data(dataset)
    .enter().append("circle")
    .attr("cx", function(d) {
        return xScale(d[0]);
    })
    .attr("cy", function(d) {
        return yScale(d[1]);
    })
    .attr("r", 5);

var yAxis = d3.axisLeft()
    .scale(yScale)
    .ticks(10);
svg.append("g")
    .attr("class", "axis")
    .attr("transform", "translate(" + margin.left + " ,0)")
    .call(yAxis);
<script src="https://d3js.org/d3.v4.min.js"></script>

Upvotes: 1

Related Questions