vrepsys
vrepsys

Reputation: 2213

Why are there gaps between rects in a D3 linechart?

I'm working on a slightly modified example of the following linechart: http://bl.ocks.org/mbostock/3883245

Here's my JS Fiddle: http://jsfiddle.net/rQ4xE/

The goal is to have blocks of background color different for periods of time. Changing color will not be difficult. However..

Problem is the gaps of different sizes between rects. I suspect this is because coordinates for the line path are decimal and something gets messed up when calculating the width for rects.

My question is what would be a good way to draw the background rects so that there are no gaps in between?

Note the gaps between grey background blocks

This is how I add the rects:

  svg.append("g").selectAll("rect")
      .data(data)
      .enter()
      .append("rect")
      .attr("class", "area")
      .attr("x", function(d) { return x(d.date) })
      .attr("y", 0)
      .attr("width", function(d, i) {
        not_last = i < data.length - 1;
        return not_last ? (x(data[i+1].date)-x(d.date)) : 0;
      })
      .attr("height", height);

Upvotes: 0

Views: 205

Answers (2)

vrepsys
vrepsys

Reputation: 2213

I believe I have found a more elegant solution.

The issue can be solved by specifying to the scale to round the numbers to the nearest integer. That can be done by using scale.rangeRound which also sets the scale's interpolator to d3.interpolateRound.

https://github.com/mbostock/d3/wiki/Quantitative-Scales#wiki-linear_rangeRound

I changed this code:

var x = d3.time.scale().range([0, width]);

to this:

var x = d3.time.scale().rangeRound([0, width]);

JS Fiddle: http://jsfiddle.net/HcC9z/2/

Upvotes: 1

LoremIpsum
LoremIpsum

Reputation: 4428

There seems to be a float issue in your x-coordinates and your widths. Try to round both of them.

svg.append("g").selectAll("rect")
  .data(data)
  .enter()
  .append("rect")
  .attr("class", "area")
  .attr("x", function(d) { return Math.floor(x(d.date)) })
  .attr("y", 0)
  .attr("width", function(d, i) {
    not_last = i < data.length - 1;
    return not_last ? (Math.floor(x(data[i+1].date))-Math.floor(x(d.date))) : 0;
  })
  .attr("height", height);

EDIT Here's a fiddle : http://jsfiddle.net/rQ4xE/3/

Upvotes: 0

Related Questions