【问题标题】:NVD3.js - How to add bar text to each bar in a stacked graph?NVD3.js - 如何将条形文本添加到堆叠图中的每个条形?
【发布时间】:2016-01-06 21:23:04
【问题描述】:

我在 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"
                                }


                                ];

【问题讨论】:

    标签: nvd3.js angular-nvd3


    【解决方案1】:

    Angular-nvd3 本身不会为多条形图执行此操作,因为动画堆叠条形图会带来一些复杂性,但它会针对离散条形图执行此操作,正如 How to display values in Stacked Multi-bar chart - nvd3 Graphs 所探讨的那样。然而,在他对该问题的回答的更新中,@Topicus 链接到 a gist they 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);
    

    【讨论】:

      【解决方案2】:

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

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

      2.添加功能以在组/堆叠选项中显示正确的文本

      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,like:

        1).initGroupLabels

        var initGroupLabels = 函数(容器,时间){ 时间=时间|| 500; container.selectAll('.nv-multibar .nv-group').each(function(group) { var g = d3.select(this); // 如果有的话,删除之前的标签 g.selectAll('text').remove(); }); $超时(函数(){ 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(container, time){ 时间=时间|| 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);
        

        }

      【讨论】:

      • 我很抱歉代码的格式,我不知道为什么会这样。 :) 我想说你需要初始化 Range 这个变量,你需要设置最大值大于默认值,这样可以避免隐藏列的最大值。分组和堆叠。
      猜你喜欢
      • 2013-07-08
      • 2022-01-21
      • 2021-03-21
      • 2023-04-09
      • 1970-01-01
      • 1970-01-01
      • 2014-05-11
      • 2020-07-03
      • 1970-01-01
      相关资源
      最近更新 更多