简体   繁体   中英

Cannot get D3 y axis and columns to align properly along x axis

A couple problems with the D3 graph I'm working on right now:

  1. I can't get the y axis to align properly on the page. The numbers over run the far left border and cannot be seen.

  2. I'd like the columns used in the bar graph to align neatly in between the tick marks and evenly spaced on either side.

Fiddle: http://jsfiddle.net/bf1gf8ep/8/

D3.js

var barWidth = 70;
var width = (barWidth + 10) * 7;
var height = 200;
var data = [{"label" : "1/7yrs", "contract" : "111830.17", "annReturn" : "1.63%"},
            {"label" : "2/7yrs", "contract" : "115311.17", "annReturn" : "2.07%"},
            {"label" : "3/7yrs", "contract" : "118984.65", "annReturn" : "2.52%"},
            {"label" : "4/7yrs", "contract" : "122859.65", "annReturn" : "2.98%"},
            {"label" : "5/7yrs", "contract" : "126947.77", "annReturn" : "3.46%"},
            {"label" : "6/7yrs", "contract" : "131260.74", "annReturn" : "3.94%"},
            {"label" : "7/7yrs", "contract" : "135810.92", "annReturn" : "4.44%"}];

 var margin = { top: 20, right: 20, bottom: 20, left: 20 };

 var chart = d3.selectAll("body").append("svg:svg")
            .attr("width", width + margin.left + margin.right)
            .attr("height", height + margin.top + margin.bottom + 20);

        var x = d3.scale.linear().domain([0, data.length]).range([0, width]);
        var y = d3.scale.linear().range([height, 0]);

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

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

  chart.append("g")
       .attr("class", "axis")
       .attr("transform", "translate(" + 10 + ",0)")
       .call(yAxis);


x = d3.scale.linear().domain([0, data.length]).range([0, width]);
y = d3.scale.linear().domain([0, 135810.92 + 1000]).range([height, 0]);

chart.selectAll("rect")
    .data(data)
    .enter()
    .append("svg:rect")
    .attr("x", function (d, i) { return x(i); })
    .attr("y", function (d) { return y(d.contract); })
    .attr("height", function (d) { return height - y(d.contract); })
    .attr("width", barWidth)
    .attr("fill", "#2d578b");

chart.selectAll("text.contractInfo")
    .data(data)
    .enter()
    .append("svg:text")
    .attr("x", function(d, i) { return x(i) + barWidth; })
    .attr("y", function(d) { return y(d.contract); })
    .attr("dx", -barWidth / 2)
    .attr("dy", "1.2em")
    .attr("text-anchor", "middle")
    .text(function(d) { return d.contract; })
    .attr("fill", "white")
    .attr("class", "contractInfo");

chart.selectAll("text.yAxis")
    .data(data)
    .enter().append("svg:text")
    .attr("x", function (d, i) { return x(i) + barWidth; })
    .attr("y", height)
    .attr("dx", -barWidth / 2)
    .attr("dy", "15px")
    .attr("text-anchor", "middle")
    .attr("style", "font-size: 12; font-family; Helvetica, sans-serif")
    .text(function (d) { return d.label; })
    .attr("transform", "translate(0, 18)")
    .attr("class", "yAxis");

Screen Shot

在此处输入图片说明

You've done all the hard work, it's just a matter of using the margin variable a little bit more. What you really want to do is push the bars to the right by 20px or margin.left and also center them. The width variable has been set to barwidth + 10 , so you want 10px padding. To center it you need to add half the padding to the barwidth. So putting these together when you create the bars you need to add margin.left and 5, that is:

.attr("x", function (d, i) { return x(i) + margin.left + 5; })

You also need to move the text using exactly the same code.

The xAxis also needed to be moved, again by adding in the margin.left value, like:

.attr("transform", "translate(" + margin.left + "," + (height) + ")");

I also noticed that you hard coded the y scale max, so I introduced ymax variable to compute the maximum and amended the y variable as below;

var ymax = d3.max(data, function(d) { return d.contract; });
var y = d3.scale.linear().domain([0, ymax]).range([height, 0]);

An alternative to the method outlined above would be to append a group element to place the bars in and translate this group by the margin variable. This would avoid having to use the margin variable in the bar geometry.

Anyway I've bumped your fiddle which contains the updates to here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM