Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

D3 axis overlap

https://jsfiddle.net/q5vwgxgz/3/

var xAxis = d3.axisBottom(x)
    .ticks(15)
  .tickSizeInner(25)

So the issue is that labels of the X axis overlap, Mon 31 and Novemeber. From what I can see the space between axes for those two dates is smaller and in result the labels overlap.
Can I solve this somehow or it's a library issue?

enter image description here

The project where that chart is used in has dateselectors for start and end date and also a dropdown for date granularity(daily, monthly, yearly) which means that I can't use a fixed number of ticks and specific format.

.ticks(15)

is used here just for the demo, in the project it's like this

Math.min(data.length, Math.floor(width / 100)) // 100 being the 'min' tick width

like image 620
Daniel Verejan Avatar asked Sep 14 '17 08:09

Daniel Verejan


1 Answers

One solution (out of many) is specifically setting the tick format...

.tickFormat(function(d) {
    return d3.timeFormat("%b %d")(d)
})

And spreading the ticks, for instance using timeDay:

.ticks(d3.timeDay.every(4))

Here is your code with those changes:

var data = [{
  "Date": "2016-09-30",
  "Jobs": 0,
}, {
  "Date": "2016-10-01",
  "Jobs": 0,
}, {
  "Date": "2016-10-02",
  "Jobs": 1,
}, {
  "Date": "2016-10-03",
  "Jobs": 0,
}, {
  "Date": "2016-10-04",
  "Jobs": 3,
}, {
  "Date": "2016-10-05",
  "Jobs": 0,
}, {
  "Date": "2016-10-06",
  "Jobs": 2,
}, {
  "Date": "2016-10-07",
  "Jobs": 0,
}, {
  "Date": "2016-10-08",
  "Jobs": 0,
}, {
  "Date": "2016-10-09",
  "Jobs": 4,
}, {
  "Date": "2016-10-10",
  "Jobs": 6,
}, {
  "Date": "2016-10-11",
  "Jobs": 1,
}, {
  "Date": "2016-10-12",
  "Jobs": 2,
}, {
  "Date": "2016-10-13",
  "Jobs": 0,
}, {
  "Date": "2016-10-14",
  "Jobs": 0,
}, {
  "Date": "2016-10-15",
  "Jobs": 0,
}, {
  "Date": "2016-10-16",
  "Jobs": 3,
}, {
  "Date": "2016-10-17",
  "Jobs": 2,
}, {
  "Date": "2016-10-18",
  "Jobs": 3,
}, {
  "Date": "2016-10-19",
  "Jobs": 3,
}, {
  "Date": "2016-10-20",
  "Jobs": 1,
}, {
  "Date": "2016-10-21",
  "Jobs": 0,
}, {
  "Date": "2016-10-22",
  "Jobs": 0,
}, {
  "Date": "2016-10-23",
  "Jobs": 4,
}, {
  "Date": "2016-10-24",
  "Jobs": 2,
}, {
  "Date": "2016-10-25",
  "Jobs": 6,
}, {
  "Date": "2016-10-26",
  "Jobs": 1,
}, {
  "Date": "2016-10-27",
  "Jobs": 1,
}, {
  "Date": "2016-10-28",
  "Jobs": 0,
}, {
  "Date": "2016-10-29",
  "Jobs": 3,
}, {
  "Date": "2016-10-30",
  "Jobs": 5,
}, {
  "Date": "2016-10-31",
  "Jobs": 0,
}, {
  "Date": "2016-11-01",
  "Jobs": 3,
}, {
  "Date": "2016-11-02",
  "Jobs": 1,
}, {
  "Date": "2016-11-03",
  "Jobs": 0,
}, {
  "Date": "2016-11-04",
  "Jobs": 0,
}, {
  "Date": "2016-11-05",
  "Jobs": 1,
}, {
  "Date": "2016-11-06",
  "Jobs": 4,
}, {
  "Date": "2016-11-07",
  "Jobs": 5,
}, {
  "Date": "2016-11-08",
  "Jobs": 6,
}, {
  "Date": "2016-11-09",
  "Jobs": 2,
}, {
  "Date": "2016-11-10",
  "Jobs": 1,
}, {
  "Date": "2016-11-11",
  "Jobs": 0,
}, {
  "Date": "2016-11-12",
  "Jobs": 2,
}, {
  "Date": "2016-11-13",
  "Jobs": 2,
}, {
  "Date": "2016-11-14",
  "Jobs": 1,
}, {
  "Date": "2016-11-15",
  "Jobs": 3,
}, {
  "Date": "2016-11-16",
  "Jobs": 0,
}, {
  "Date": "2016-11-17",
  "Jobs": 1,
}, {
  "Date": "2016-11-18",
  "Jobs": 0,
}, {
  "Date": "2016-11-19",
  "Jobs": 0,
}, {
  "Date": "2016-11-20",
  "Jobs": 1,
}, {
  "Date": "2016-11-21",
  "Jobs": 2,
}, {
  "Date": "2016-11-22",
  "Jobs": 2,
}, {
  "Date": "2016-11-23",
  "Jobs": 4,
}, {
  "Date": "2016-11-24",
  "Jobs": 0,
}, {
  "Date": "2016-11-25",
  "Jobs": 0,
}]
var parseTime = d3.timeParse("%Y-%m-%d");
data.forEach(function(d) {
  d.Date = parseTime(d.Date);
});

var svg = d3.select("svg"),
  margin = {
    top: 20,
    right: 20,
    bottom: 50,
    left: 50
  },
  width = +svg.attr("width") - margin.left - margin.right,
  height = +svg.attr("height") - margin.top - margin.bottom,
  g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var x = d3.scaleTime()
  .rangeRound([0, width]);
var y = d3.scaleLinear()
  .rangeRound([height, 0]);

var line = d3.line()
  .x(function(d) {
    return x(d.Date);
  })
  .y(function(d) {
    return y(d.Jobs);
  });

x.domain(d3.extent(data, function(d) {
  return d.Date;
}));
y.domain(d3.extent(data, function(d) {
  return d.Jobs;
}));

var xAxis = d3.axisBottom(x)
  .ticks(d3.timeDay.every(4))
  .tickFormat(function(d) {
    return d3.timeFormat("%b %d")(d)
  })
  .tickSizeInner(25)
g.append("g")
  .attr("transform", "translate(0," + height + ")")
  .call(xAxis)
  .select(".domain")
  .remove();

g.append("g")
  .call(d3.axisLeft(y))
  .append("text")
  .attr("fill", "#000")
  .attr("transform", "rotate(-90)")
  .attr("y", 6)
  .attr("dy", "0.71em")
  .attr("text-anchor", "end")
  .text("Jobs");

g.append("path")
  .datum(data)
  .attr("fill", "none")
  .attr("stroke", "steelblue")
  .attr("stroke-linejoin", "round")
  .attr("stroke-linecap", "round")
  .attr("stroke-width", 1.5)
  .attr("d", line);
<svg width="1200" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>

However, have in mind that in D3 time scales were not created having customizations in mind. Their behaviour is dynamic. Therefore, You'll have to fix each specific problem using ad hoc solutions.

like image 75
Gerardo Furtado Avatar answered Nov 10 '22 17:11

Gerardo Furtado