NVD3.js - 如何将条形文本添加到堆叠图形中的每个条形图?

时间:2016-01-06 21:23:05

标签: nvd3.js angular-nvd3

我在NVD3 / AngularJS中创建了一个多条形图。我想在每个矩形条中显示文本及其值,如下面的JSON所示。

如何在每个栏中向图表显示文字值?

NVD3图表定义

multiBarChart: {
        options: function(){
          return {
            chart: {
              type: 'multiBarChart',
              stacked: true,
              x: function(d){return d.x;},
              y: function(d){return d.y;},
              text: function(d){return d.x;},
              showLabels: true,
              showLegend: false,
              transitionDuration: 500,
              forceX: ["Team", "Meeting", "Phase", "Source"],
              xAxis: {
                axisLabel: 'Category',
                axisLabelDistance: -8
              },
              yAxis: {
                axisLabel: 'Number Of Action Items',
              }
            }
          }
        },
        data: categoryChartData
      }

JSON数据(categoryChartData)

  [ 
                                {"values" : [
                                    {
                                        "y" :10,
                                        "x" : "Team"
                                    }, {
                                        "y" : 0,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :0,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 0,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Team1"
                                },

                                {"values" : [
                                    {
                                        "y" :5,
                                        "x" : "Team"
                                    }, {
                                        "y" : 0,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :0,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 0,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Team2"
                                },
                                    {"values" : [
                                    {
                                        "y" :0,
                                        "x" : "Team"
                                    }, {
                                        "y" : 7,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :0,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 0,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Meeting1"
                                },
                                    {"values" : [
                                    {
                                        "y" :0,
                                        "x" : "Team"
                                    }, {
                                        "y" : 3,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :0,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 0,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Meeting2"
                                },
                                {"values" : [
                                    {
                                        "y" :0,
                                        "x" : "Team"
                                    }, {
                                        "y" : 0,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :9,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 0,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Phase1"
                                },
                                {"values" : [
                                    {
                                        "y" :0,
                                        "x" : "Team"
                                    }, {
                                        "y" : 0,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :5,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 0,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Phase1"
                                },
                                {"values" : [
                                    {
                                        "y" :0,
                                        "x" : "Team"
                                    }, {
                                        "y" : 0,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :0,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 2,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Internal"
                                },
                                {"values" : [
                                    {
                                        "y" :0,
                                        "x" : "Team"
                                    }, {
                                        "y" : 0,
                                        "x" : "Meeting"
                                    },
                                    {
                                        "y" :0,
                                        "x" : "Phase"
                                    }, {
                                        "y" : 1,
                                        "x" : "Source"
                                    }
                                    ],
                                    "key" : "Customer"
                                }


                                ];

Category Stacked Chart

2 个答案:

答案 0 :(得分:4)

Angular-nvd3本身不会对多条形图进行此操作,因为动画叠加条形图会产生一些复杂性,但对于离散条形图,它将用this previous stackoverflow question进行探索。但是,在对该问题的回答的更新中,@ Topicus链接到a gist he/she wrote,以完成您正在寻找的内容。

我根据你的情况调整了要点;你可以在this plunker中看到结果。如果标签显示有点不稳定,您可以稍微使用格式。关键是在动画完成后需要附加标签,因此我设置一个超时等于(也可能稍大于)transitionDuration图表属性的值。我还删除了所有零值,因此它们不会模糊非零值。

$scope.options = {
  chart: {
    type: 'multiBarChart',
    height: 500,
    transitionDuration: 500,
    ...
  }
};

$scope.data...

$timeout(function () {
  d3.selectAll('.nv-multibar .nv-group').each(function(group){
    var g = d3.select(this);

    // Remove previous labels if there is any
    g.selectAll('text').remove(); 
    g.selectAll('.nv-bar').each(function(bar){
    var b = d3.select(this);
    var barWidth = b.attr('width');
    var barHeight = b.attr('height');

    g.append('text')
      // Transforms shift the origin point then the x and y of the bar
      // is altered by this transform. In order to align the labels
      // we need to apply this transform to those.
      .attr('transform', b.attr('transform'))
      .text(function(){
        // No decimals format and eliminate zero values
        if (bar.y === 0) {
          return;
        }
        return parseFloat(bar.y).toFixed(0);
      })
      .attr('y', function(){
        // Center label vertically
        var height = this.getBBox().height;
        return parseFloat(b.attr('y')) + 15; // 15 is the label's margin from the top of bar
      })
      .attr('x', function(){
        // Center label horizontally
        var width = this.getBBox().width;
        return parseFloat(b.attr('x')) + (parseFloat(barWidth) / 2) - (width / 2);
      })
      .style("stroke","black")
      .attr('class', 'bar-values');
    });
  });
}, 500);

希望这有助于您入门。

答案 1 :(得分:0)

我认为答案有两点要补充。 1.我们添加代码,在回调函数中添加值文本。

callback: function(chart){
    chart.dispatch.on('stateChange', function(e){
        setMultiBarValue(e.stacked);
    });

    setMultiBarValue(config.stacked);
}

2.add函数可在组/堆叠选项中显示正确的文本

function setMultiBarValue(chart, config, dataRange, stacked, time){
    if(config.type === 'multiBarChart'){
        if(stacked === true){
            //stack set your totalMin, totalMax to make all the value visible.
            chart.yDomain([dataRange.totalMin, dataRange.totalMax]);
            initStackLables(d3.select(chart.container), time || 1000);
        }else{
            //group: set your min,max to make all the value visible.
            chart.yDomain([dataRange.yMin, dataRange.yMax]);
            initGroupLabels(d3.select(chart.container), time || 1000);
        }
    }
}
  1. 定义拖曳函数initStackLables,initGroupLabels,例如:

    1).initGroupLabels

    var initGroupLabels = function(Container,time){         时间=时间|| 500;         container.selectAll('。nv-multibar .nv-group')。each(function(group){             var g = d3.select(this);             //删除以前的标签(如果有的话)             g.selectAll('text')。remove();         });         $ timeout(function(){             container.selectAll('。nv-multibar .nv-group')。each(function(group){                 var g = d3.select(this);

                g.selectAll('.nv-bar').each(function(bar, index) {
                    var b = d3.select(this);
                    var barWidth = b.attr('width');
                    var barHeight = b.attr('height');
    
                    g.append('text')
                    // Transforms shift the origin point then the x and y of the bar
                    // is altered by this transform. In order to align the labels
                    // we need to apply this transform to those.
                    .attr('transform', b.attr('transform')).text(function() {
                        // No decimals format and eliminate zero values
                        if (bar.y === 0) {
                            return;
                        }
                        return parseFloat(bar.y);
                    }).attr('y',
                    function() {
                        // Center label vertically
                        var height = this.getBBox().height;
                        return parseFloat(b.attr('y')) - 10; // 10 is the label's margin from the top of bar
                    }).attr('x',
                    function() {
                        // Center label horizontally
                        var width = this.getBBox().width;
                        return parseFloat(b.attr('x')) + (parseFloat(barWidth) / 2) - (width / 2);
                    }).style('stroke', 'black').attr('class', 'bar-values');
                });
            });
        },
        time);
    }
    

    2)initStackLables

    var initStackLables = function(容器,时间){     时间=时间|| 500;

    container.selectAll('.nv-multibar .nv-group').each(function(group){
        var g = d3.select(this);
        // Remove previous labels if there is any
        g.selectAll('text').remove(); 
    });
    $timeout(function () {
        var length = container.selectAll('.nv-multibar .nv-group').length;
        var vArr = []; var yArr = [];
        container.selectAll('.nv-multibar .nv-group').each(function(group){
            var g = d3.select(this);
            g.selectAll('.nv-bar').each(function(bar, index){
                var b = d3.select(this); var by = parseFloat(b.attr('y'));
                var barHeight = b.attr('y');
                vArr[index] = vArr[index] || 0;
                vArr[index] += parseFloat(bar.y) || 0;
                yArr[index] = yArr[index] || by;
                yArr[index] = yArr[index] > by ? by : yArr[index];
            });
        });
        container.selectAll('.nv-multibar .nv-group').each(function(group, index){
            if(index === 0){
                var g = d3.select(this);
                // Remove previous labels if there is any
                g.selectAll('text').remove(); 
                g.selectAll('.nv-bar').each(function(bar, index){
                    var b = d3.select(this);
                    var barWidth = b.attr('width');
                    var barHeight = b.attr('height');
    
                    g.append('text')
                        .attr('transform', b.attr('transform'))
                        .text(function(){
                            if (bar.y === 0) {
                                return;
                            }
                            return parseFloat(vArr[index];
                        })
                        .attr('y', function(){
                            var height = this.getBBox().height;
                            return parseFloat(yArr[index]) - 10; // 10 is the label's margin from the top of bar
                        })
                        .attr('x', function(){
                            var width = this.getBBox().width;
                            return parseFloat(b.attr('x')) + (parseFloat(barWidth) / 2) - (width / 2);
                        })
                        .style('stroke','black')
                        .attr('class', 'bar-values');
                });
            }
        });
    
    }, time);
    

    }