如何在Stacked Multi-bar chart - nvd3 Graphs中显示值

时间:2015-06-03 13:14:57

标签: angularjs d3.js nvd3.js angularjs-nvd3-directives

我有一个场景,我需要在堆叠的多条形图中显示每个堆栈的值 - nvd3图形,因为我们可以在离散值 - nvd3图形中显示值。

我理解,'{3}}中使用'showvalue',我们可以在堆叠图中使用showvalue,如果没有,请使用替代解决方案建议。

提前致谢

1 个答案:

答案 0 :(得分:8)

目前还不可能。该选项仅在离散条形图中可用。

来自维护者:

  

我们没有这种能力。 Stacked / Grouped图表也有复杂的动画,这使得解决这个问题变得棘手。我们改用工具提示。

来源https://github.com/novus/nvd3/issues/150

如果你想这样做,你需要使用d3进行自己的实现。这里有一个很好的例子http://plnkr.co/edit/BNpAlFalKz0zkkSszHh1?p=preview。它使用角度包装,但它是一个很好的起点。

var app = angular.module('app', ['nvd3ChartDirectives']);

app.controller('chartCtrl', function($scope, $timeout) {

  var ANIMATION_TIME = 1500,
    countSeriesDisplayed = 2,
    promise,
    labels = ["label1", "label2", "label3", "label4", "label5"];

  $scope.isStacked = false;

  // Example data
  $scope.chartData = [{
    "key": "Series 1",
    "values": [
      [0, 10],
      [1, 20],
      [2, 30],
      [3, 40],
      [4, 50]
    ]
  }, {
    "key": "Series 2",
    "values": [
      [0, 10],
      [1, 40],
      [2, 60],
      [3, 20],
      [4, 40]
    ]
  }];

  /* To add labels, images, or other nodes on the created SVG, we need to wait
   *  for the chart to be rendered with a callback.
   *  Once the chart is rendered, a timeout is set to wait for the animation to
   *  finish.
   *
   *  Then, we need to find the position of the labels and set it with the
   *  transform attribute in SVG.
   *  To do so, we have to get the width and height of each bar/group of bar 
   *  which changes if stacked or not
   *
   */

  // Callback called when the chartData is assigned
  $scope.initLabels = function() {
    return function(graph) {
      promise = $timeout(function() {
        var svg = d3.select("svg"),
          lastRects, rectWidth,
          heightForXvalue = []; // Used for grouped mode

        // We get one positive rect of each serie from the svg (here the last serie)
        lastRects = svg.selectAll("g.nv-group").filter(
          function(d, i) {
            return i == countSeriesDisplayed - 1;
          }).selectAll("rect.positive");

        if ($scope.isStacked) {
          // If stacked, we get the width of one rect
          rectWidth = lastRects.filter(
            function(d, i) {
              return i == countSeriesDisplayed - 1;
            }).attr("width");
        } else {
          // If grouped, we need to get the greatest height of each bar
          var nvGroups = svg.selectAll("g.nv-group").selectAll("rect.positive");
          nvGroups.each(
            function(d, i) {
              // Get the Min height space for each group (Max height for each group)
              var rectHeight = parseFloat(d3.select(this).attr("y"));
              if (angular.isUndefined(heightForXvalue[i])) {
                heightForXvalue[i] = rectHeight;
              } else {
                if (rectHeight < heightForXvalue[i]) {
                  heightForXvalue[i] = rectHeight;
                }
              }
            }
          );

          // We get the width of one rect multiplied by the number of series displayed
          rectWidth = lastRects.filter(
            function(d, i) {
              return i == countSeriesDisplayed - 1;
            }).attr("width") * countSeriesDisplayed;
        }

        // We choose a width equals to 70% of the group width
        var labelWidth = rectWidth * 70 / 100;

        var groupLabels = svg.select("g.nv-barsWrap").append("g");

        lastRects.each(
          function(d, index) {
            var transformAttr = d3.select(this).attr("transform");
            var yPos = parseFloat(d3.select(this).attr("y"));
            groupLabels.append("text")
              .attr("x", (rectWidth / 2) - (labelWidth /2)) // We center the label
              // We add a padding of 5 above the highest rect
              .attr("y", (angular.isUndefined(heightForXvalue[index]) ? yPos : heightForXvalue[index]) - 5)
              // We set the text
              .text(labels[index])
              .attr("transform", transformAttr)
              .attr("class", "bar-chart-label");
          });

      }, ANIMATION_TIME);
    }
  };

  // Tooltips
  $scope.toolTipContentFunction = function () {
    return function (key, x, y, e, graph) {
      return labels[x];
    }
};

  $scope.$on('$destroy', function () {
    // Cancel timeout if still active
    $timeout.cancel(promise);
  });

});

<强>更新

我已经创建了一个可以帮助您自己实现这一目标的要点。

https://gist.github.com/topicus/217444acb4204f364e46