【问题标题】:d3 how to make single stacked column chartd3如何制作单堆积柱形图
【发布时间】:2016-04-02 19:28:01
【问题描述】:

我正在尝试让 d3 绘制单个堆叠条形图,如下所示:

<svg width = '500' height= '100'>
<rect x='0' y='0' width='224' height='30' fill='green'/>
<rect x='224' y='0' width='84' height='30' fill='blue'/>
<rect x='308' y='0' width='29' height='30' fill='darkgray'/>
<rect x='337' y='0' width='3' height='30' fill='#606060'/>
</svg>

如您所见,x 位置从零开始,然后每个后续 x 位置都等于前面宽度的总和。

所以我试图让 d3 从一个名为 datavars 的数组中绘制类似的东西:

var datavars = [224, 84, 29, 3];

...并确保 d3 将正确的宽度值分配给正确的 x 值,我创建了这些变量:

var prev_width0 = 0;
var prev_width1 = datavars[0];
var prev_width2 =  datavars[0] +  datavars[1];
var prev_width3 =  datavars[0] +  datavars[1] +  datavars[2];

... 并像这样定义 x 值:

//create SVG element
var svg = d3.select('body')
.append('svg')
.attr('width', w)
.attr('height', h);

svg.selectAll('rect')
.data(datavars)
.enter()
.append('rect')
.attr('width', function(d){
    return d;})
               .attr('x',function(d, i){
               return 'prev_width'+i; })
.attr('y',0)
.attr('height', 30);

正如您可能已经猜到的那样,强缩进函数(基于前面宽度的总和,并在prev_width 变量中定义)为每次迭代(prev_width0、prev_width1 等)返回一个字符串,并且 不是我认为我在创建 prev_width 变量时定义的值。

我显然错误地定义了变量。知道如何正确执行此操作吗?

【问题讨论】:

    标签: javascript d3.js var


    【解决方案1】:

    这是一个 sn-p(我的方法有点不同)

    //this function deals with pairing finding x for each width in the array and add them to a new array called x_and_width_values
    //example :[[0,224],[84,224],[29,308],[3,337]]
    //           ^  ^    ^   ^    ^   ^    ^  ^
    //          x width  x  width  .............
    function combinations(prev,current,index,arr){
    // This method focus on accummulating results by reference previous and current element
    //for the first and second element we need specifically add this
    if(index==1){
    x_and_width_values.push([arr[index-1],0]);
    x_and_width_values.push([arr[index],prev])
    }
    //other elements we use index as follows;
    else{
    x_and_width_values.push([arr[index],prev])
    }
    return prev+current
    }
    //after creating an array with all [x,width] combination, we map it to colors to get out final array
    //example :[[[0,224],'green'],[[84,224],'blue'],[29,308],[[3,337],'darkgray']
    function colors_with_combination(e, i) {
        return [x_and_width_values[i], colors[i]];
       }
    
    //*******************acutal beef og code***************
    var x_and_width_values=[];
    //this link is needed to creation of svg elements
    var link="http://www.w3.org/2000/svg"
    //all your widths
    var all_widths=[224,84,29,3];
    //all your colors
    var colors=['green','blue','darkgray','#606060'];
    //sort your width array to be on the safe side
    all_widths.sort(function(a,b){return b-a});
    //find all width and x  combination
    all_widths.reduce(combinations);
    //map width and x values to color values
    var all = x_and_width_values.map(colors_with_combination);
    //create a  loop for object creation
    for(var i=0;i<all.length;++i){
    var rect=document.createElementNS(link,'rect');
    rect.setAttributeNS(null,'x',all[i][0][1])
    rect.setAttributeNS(null,'width',all[i][0][0]);
    rect.setAttributeNS(null,'fill',all[i][1]);
    rect.setAttributeNS(null,'height','30');
    rect.setAttributeNS(null,'y','0');
    document.getElementById('svg').appendChild(rect);;
    }
    <svg id='svg' width = '500' height= '100'>
    </svg>

    【讨论】:

      【解决方案2】:

      JavaScript 不会将字符串 "datavars1" 解释为变量 datavars1。要将字符串解释为 JavaScript 变量,您可以使用 eval()。所以将:return 'prev_width'+i; }) 更改为 return eval('prev_width'+i); })。虽然更好的主意可能是使用数组,例如:

      var prev_width = [0,
                        datavars[0],
                        datavars[0] +  datavars[1],
                        datavars[0] +  datavars[1] +  datavars[2]
                       ];
      
      ...
         .attr('x',function(d, i){
         return prev_width[i]; })
      

      Fiddle Example

      你可以用颜色做类似的事情:

      var colors = ['green','blue','darkgray','#606060'];
      
      ...
      .attr('fill', function(d, i){ return colors[i]; })
      

      Bar chart with color

      您还可以创建一个对象数组来存储颜色、宽度等。


      一个更具可扩展性的想法是摆脱数组prev_width,并拥有一个可以将总和计算到一个点的函数。如:

      function sum(array, start, end) {
          var total = 0;
          for(var i=start; i<end; i++) total += array[i];
          return total;
      }
      

      那么你可以这样做:

      ...
         .attr('x',function(d, i){
         return sum(datavars, 0, i); })
      

      Example using summation

      【讨论】:

      • 啊...这些非常好,谢谢一百万。你的第一个建议是我一直在努力的,接下来的几个要优雅得多。非常感谢
      猜你喜欢
      • 1970-01-01
      • 2013-06-26
      • 1970-01-01
      • 1970-01-01
      • 2010-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多