如何制作d3js中的基本列(垂直)图表?

问题描述:

我正在尝试d3js,并且遇到了第一个基本列(垂直条形图)工作的问题。我觉得唯一难以理解的是缩放比例。我想使x和y轴带标签的蜱,但我有以下问题:如何制作d3js中的基本列(垂直)图表?

首先这里是我的数据:

{ 
"regions": 
["Federal","Tigray","Afar","Amhara","Oromia","Gambella","Addis Ababa","Dire Dawa","Harar","Benishangul-Gumuz","Somali","SNNPR "], 
"institutions": 
[0,0,34,421,738,0,218,22,22,109,0,456] 
} 
  1. 在y轴上的值是否有但顺序颠倒了。这里是代码:

    var y = d3.scale.linear()。domain([0,d3.max(data.institutions)])。range([0,height]);

然后我用这个尺度来创建一个y轴:

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

与该轴添加到SVG元素

svgContainer.append("g") 
     .attr("class", "y axis") 
     .call(yAxis) 
      .append("text") 
      .attr("transform", "rotate(-90)") 
      .attr("y", 6) 
      .attr("dy", ".71em") 
      .style("text-anchor", "end") 
      .text("Institutions"); 

这里的问题是,y轴从顶部的0开始,底部的700开始,但它应该是相反的顺序。

另一个问题,我有它的X轴。我想要有一个序数标度,因为我想要的值是在上面的区域名称中。所以这就是我所做的。

var x = d3.scale.ordinal() 
        .domain(data.regions.map(function(d) { return d.substring(0, 2); })) 
        .rangeRoundBands([0, width], .1); 

然后轴线

var xAxis = d3.svg.axis() 
         .scale(x) 
         .orient("bottom"); 

,最后将它添加到SVG元素

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

这里的问题是蜱以及标签出现,但它们不间隔开均匀,不符合我绘制矩形的中心。这里是完整的代码,所以你可以看到发生了什么。

$(document).ready(function(){ 

    d3.json("institutions.json", draw); 

}); 

function draw(data){ 
    var margin = {"top": 10, "right": 10, "bottom": 30, "left": 50}, width = 700, height = 300; 

    var x = d3.scale.ordinal() 
        .domain(data.regions.map(function(d) { return d.substring(0, 2); })) 
        .rangeRoundBands([0, width], .1); 


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

    var xAxis = d3.svg.axis() 
         .scale(x) 
         .orient("bottom");  

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

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

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

    svgContainer.append("g") 
        .attr("class", "y axis") 
        .call(yAxis) 
       .append("text") 
        .attr("transform", "rotate(-90)") 
        .attr("y", 6) 
        .attr("dy", ".71em") 
        .style("text-anchor", "end") 
        .text("Institutions"); 

    svgContainer.selectAll(".bar") 
     .data(data.institutions) 
     .enter() 
     .append("rect") 
     .attr("class", "bar") 
     .attr("x", function(d, i) {return i* 41;}) 
     .attr("y", function(d){return height - y(d);}) 
     .attr("width", x.rangeBand()) 
     .attr("height", function(d){return y(d);}); 

} 
+1

你应该考虑在[的jsfiddle(http://jsfiddle.net/),或在[bl.ocks(http://bl.ocks.org/)介绍你的示例代码。使人们更容易看到你在做什么并帮助你。 – seliopou

我把代码给小提琴:http://jsfiddle.net/GmhCr/4/

随意编辑它!我已经解决了这两个问题。


要解决倒置y轴只是交换的范围功能参数的值:

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

不要忘记,如果你改变比例调整为酒吧的代码!


酒吧和x轴之间的不匹配的来源可以在这里找到:

var x = d3.scale.ordinal() 
    .domain(data.regions.map(function(d) { 
     return d.substring(0, 2);})) 
    .rangeRoundBands([0, width], .1); 

svgContainer.selectAll(".bar") 
    .data(data.institutions) 
    .enter() 
    .append("rect") 
    .attr("class", "bar") 
    .attr("x", function(d, i) {return i* 41;}) 
    .attr("y", function(d){return height - y(d);}) 
    .attr("width", x.rangeBand()) 
    .attr("height", function(d){return y(d);}); 

您在0.1指定rangeRoundBands填充但计算x和宽度时忽略填充棒的值。例如,对于填充为0的数据是正确的:

var x = d3.scale.ordinal() 
    .domain(data.regions.map(function(d) { 
     return d.substring(0, 2);})) 
    .rangeRoundBands([0, width], 0); 

svgContainer.selectAll(".bar").data(data.institutions).enter().append("rect") 
    .attr("class", "bar") 
    .attr("x", function(d, i) { 
     return i * x.rangeBand(); 
    }) 
    .attr("y", function(d) { 
     return y(d); 
    }) 
    .attr("width", function(){ 
     return x.rangeBand(); 
    }) 
    .attr("height", function(d) { 
     return height -y(d); 
    }); 

填充确定为填充保留多少域。当使用700的宽度和0.1的填充时,恰好70像素用于填充。这意味着你必须为每个条的x值添加70个数据[“区域”]长度像素,以便使用填充工作。

+0

非常感谢您的帮助!它终于看起来像我想要的样子。线性标尺非常直接,它很有意义,但我无法绕开序数标度。困扰我的一件事是在你原来的jsfiddle页面中,条形之间没有间隙。我如何获得? – tsega