문제

I am working on a d3 chart that uses a time.scale and rects and I am stuck on a very small issue. Either the x axis is not extending the full length of its svg container (so the x axis is not under that last bar) or the x position of the rects is somehow not properly taking the range into account. I have tried looking through several examples and many stackoverflow posts but so far I can't figure out where I've screwed up. Thank you!

Here is my code:

var margin = {top:30, right:30, bottom:30, left:30},
    width = 600 - margin.right - margin.left,
    height = 300 - margin.top - margin.bottom;  


var parseDate =  d3.time.format("%d-%b-%y").parse;

var formatTime = d3.time.format("%e %B");                 


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

var y = d3.scale.linear().range([height, 0]);



var xAxis = d3.svg.axis()
            .scale(x)
            .orient("bottom")
            .tickFormat(d3.time.format("%b %y"));                       


var yAxis = d3.svg.axis()
            .scale(y)
            .orient("left")
            .ticks(5);  

var svg = d3.select("body").append("svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height",height + margin.top + margin.bottom)
            .append("g")
            .attr("transform" , "translate(" + margin.left + "," + margin.top + ")");





d3.tsv("data/months.tsv", function(error, data) {
data.forEach(function(d) {
        d.month =  parseDate(d.month);
        d.value = +d.value;  //ensures variable is treated like a number

    }); 


   x.domain(d3.extent(data, function(d) { return d.month; }));
   y.domain([0,d3.max(data,function(d) { return d.value; })]);

   var barPadding = 4;

   var barWidth = width/data.length - barPadding;

   var rects = svg.selectAll("rect")
                .data(data)
                .enter().append("rect")
                .attr("class" , "bar")
                .attr("x", function(d) { return x(d.month); })  // I think the problem is here
                .attr("y", function(d) { return y(d.value); })  
                .attr("width", barWidth )   
                .attr("height", function(d) { return height - y(d.value); });           



    svg.append("g")
            .attr("class", "axis")
            .attr("transform","translate(0, " + height + ")")
            .call(xAxis);

            svg.append("g")
            .attr("class" , "axis") 
            .call(yAxis);                   

});

Thank you in advance!

도움이 되었습니까?

해결책

The problem is that you're starting the bars at the position of the ticks. That is, the left hand side of the bar is aligned with the respective tick, creating the impression that the bar isn't aligned because it is off center.

To fix, simply subtract barWidth/2 as an offset to the x position of the bars. You'll also want to adjust the output range of your x scale such that the y axis and the first bar don't overlap.

x.range([barWidth/2, width]);
// etc.
rects.attr("x", function(d) { return x(d.month) - barWidth/2; })

Complete example here.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top