FallingSkies
FallingSkies

Reputation: 121

Providing X axis with proper tick values

<!DOCTYPE html>
<html lang="en">
<head>
  <style>
    .axis path {
      fill: none;
      stroke: #777;
      shape-rendering: crispEdges;
    }
    .axis text {
      font: 10px sans-serif;
    }
  </style>
</head>
<body>
  <svg id="visualization" width="1000" height="500"></svg>
</body>
</html>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<script>
function InitChart() {
    var data = [{
        "sale": "215",
        "calendarDate": "20140302"
    }, {
        "sale": "179",
        "calendarDate": "20140303"
    }, {
        "sale": "199",
        "calendarDate": "20140304"
    }, {
        "sale": "134",
        "calendarDate": "20140305"
    }, {
        "sale": "176",
        "calendarDate": "20140306"
    }];
    var vis = d3.select("#visualization"),
        WIDTH = 1000,
        HEIGHT = 500,
        MARGINS = {
            top: 20,
            right: 20,
            bottom: 20,
            left: 50
        },
        calendarDatesAsStrings = ['02.03.2014','03.03.2014','04.03.2014','05.03.2014','06.03.2014'],
        xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([20140302, 20140306]),
        yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([124, 225]),
        xAxis = d3.svg.axis().scale(xScale),
        yAxis = d3.svg.axis().scale(yScale).orient("left");

    vis.append("svg:g")
        .attr("class", "x axis")
        .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
        .call(xAxis)
        .selectAll('text')
        .text(function (d, i) { return calendarDatesAsStrings[i]; });

    vis.append("svg:g")
        .attr("class", "y axis")
        .attr("transform", "translate(" + (MARGINS.left) + ",0)")
        .call(yAxis);

    var lineGen = d3.svg.line()
        .x(function(d) {
            return xScale(d.calendarDate);
        })
        .y(function(d) {
            return yScale(d.sale);
        });

    vis.append('svg:path')
        .attr('d', lineGen(data))
        .attr('stroke', 'green')
        .attr('stroke-width', 2)
        .attr('fill', 'none');
}
InitChart();
</script>

http://jsbin.com/zupejizeho/1/edit

I expected the labels to be in their right positions, they aren't.

Instead, they look like they are "compressed" and placed every half-segment instead of full segment.

What am I doing wrong?

Upvotes: 0

Views: 380

Answers (2)

Mark
Mark

Reputation: 108522

You have a decision to make here. Treat your dates as strings and use an ordinal scale or you treat your dates as dates and use a time scale. Right now you are using a linear scale which does not map nicely to date stamps.

Since your dataset is pretty limited an ordinal scale is probably easier:

 // map all my dates to an ordinal 
 // with points separated nicely in my range
 xScale = d3.scale.ordinal()
   .rangePoints([MARGINS.left, WIDTH - MARGINS.right])
   .domain(data.map(function(d){ return d.calendarDate })),  

And format the date strings:

// then reformat the strings to what you want with some format helpers
oldFormat = d3.time.format("%Y%m%d"),
newFormat = d3.time.format("%m.%d.%Y");

xAxis = d3.svg.axis()
  .scale(xScale)
  .orient("bottom")
  .tickFormat(function(d){
    var dateTime = oldFormat.parse(d); // parse the string to date
    return newFormat(dateTime); // format it back to appropriate string
  }),

Updated example here.

If you get a little more data complexity, you'll probably want to shift to really treating your dates as dates. So, first, fix your data:

data = data.map(function(d){ 
  return {
    sale: +d.sale, // this is really a numeric
    calendarDate: oldFormat.parse(d.calendarDate) // this be a datetime now
  }
});

Set up your scale with time:

xScale = d3.time.scale()
  .range([MARGINS.left, WIDTH - MARGINS.right])
    .domain(
      [d3.min(data.map(function(d){ return d.calendarDate })),
        d3.max(data.map(function(d){ return d.calendarDate }))]
    ),

And the format becomes simpler:

xAxis = d3.svg.axis()
  .scale(xScale)
  .orient("bottom")
  .tickFormat(d3.time.format("%m.%d.%Y")),

Here an example of this.

Upvotes: 1

tomtomtom
tomtomtom

Reputation: 1522

you don't need to add the last two rows after the call of the xAxis, here:

vis.append("svg:g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
    .call(xAxis)
    .selectAll('text')
    .text(function (d, i) { return calendarDatesAsStrings[i]; });

you simply have to call the xAxis and that's it, working link: http://jsbin.com/yabecihihi/1/edit?html,output (the dates need to be parsed properly with a time scale tho)

Upvotes: 0

Related Questions