Search code examples
htmlrazormorris.js

How to display count value of each category of Y axis in a graph using Morris.Bar function?


I am displaying data in graphical format and I am using Morris.Bar function in my cshtml page. The Y axis has categories namely: Performance, Maintainability, Others, Portability, Reliability and Security.

I am using the following function:

Morris.Bar({
    element: 'category-bar-chart',
    data: JSON.parse(''[{"y":"Performance","a":23},{"y":"Maintainability","a":106},{"y":"Others","a":98},{"y":"Portability","a":27},{"y":"Reliability","a":87},{"y":"Security","a":14}]'),'),
    xkey: 'y',
    ykeys: ['a'],
    labels: ['Violation'],
    xLabelAngle: 43,            
});

But currently it is not displaying the value for each category at the top of each bar. May I know what property I can add to get the values at the top of each bar?


Solution

  • There's no built-in parameter to display the value on top of each Bar.

    But you can extend Morris to add this parameter. I've extended Morris, adding a labelTop property for Bar charts. If set to true, a label with the value is added on top of each Bar (I restricted this property for non stacked Bar, as there's multiple values with stacked Bar).

    Usage:

    labelTop: true
    

    Please try the snippet below to see a working example:

    (function() {
      var $, MyMorris;
    
      MyMorris = window.MyMorris = {};
      $ = jQuery;
    
      MyMorris = Object.create(Morris);
    
      MyMorris.Bar.prototype.defaults["labelTop"] = false;
    
      MyMorris.Bar.prototype.drawLabelTop = function(xPos, yPos, text) {
        var label;
        return label = this.raphael.text(xPos, yPos, text).attr('font-size', this.options.gridTextSize).attr('font-family', this.options.gridTextFamily).attr('font-weight', this.options.gridTextWeight).attr('fill', this.options.gridTextColor);
      };
    
      MyMorris.Bar.prototype.drawSeries = function() {
        var barWidth, bottom, groupWidth, idx, lastTop, left, leftPadding, numBars, row, sidx, size, spaceLeft, top, ypos, zeroPos;
        groupWidth = this.width / this.options.data.length;
        numBars = this.options.stacked ? 1 : this.options.ykeys.length;
        barWidth = (groupWidth * this.options.barSizeRatio - this.options.barGap * (numBars - 1)) / numBars;
        if (this.options.barSize) {
          barWidth = Math.min(barWidth, this.options.barSize);
        }
        spaceLeft = groupWidth - barWidth * numBars - this.options.barGap * (numBars - 1);
        leftPadding = spaceLeft / 2;
        zeroPos = this.ymin <= 0 && this.ymax >= 0 ? this.transY(0) : null;
        return this.bars = (function() {
          var _i, _len, _ref, _results;
          _ref = this.data;
          _results = [];
          for (idx = _i = 0, _len = _ref.length; _i < _len; idx = ++_i) {
            row = _ref[idx];
            lastTop = 0;
            _results.push((function() {
              var _j, _len1, _ref1, _results1;
              _ref1 = row._y;
              _results1 = [];
              for (sidx = _j = 0, _len1 = _ref1.length; _j < _len1; sidx = ++_j) {
                ypos = _ref1[sidx];
                if (ypos !== null) {
                  if (zeroPos) {
                    top = Math.min(ypos, zeroPos);
                    bottom = Math.max(ypos, zeroPos);
                  } else {
                    top = ypos;
                    bottom = this.bottom;
                  }
                  left = this.left + idx * groupWidth + leftPadding;
                  if (!this.options.stacked) {
                    left += sidx * (barWidth + this.options.barGap);
                  }
                  size = bottom - top;
                  if (this.options.verticalGridCondition && this.options.verticalGridCondition(row.x)) {
                    this.drawBar(this.left + idx * groupWidth, this.top, groupWidth, Math.abs(this.top - this.bottom), this.options.verticalGridColor, this.options.verticalGridOpacity, this.options.barRadius, row.y[sidx]);
                  }
                  if (this.options.stacked) {
                    top -= lastTop;
                  }
                  this.drawBar(left, top, barWidth, size, this.colorFor(row, sidx, 'bar'), this.options.barOpacity, this.options.barRadius);
                  _results1.push(lastTop += size);
    
                  if (this.options.labelTop && !this.options.stacked) {
                    label = this.drawLabelTop((left + (barWidth / 2)), top - 10, row.y[sidx]);
                    textBox = label.getBBox();
                    _results.push(textBox);
                  }
                } else {
                  _results1.push(null);
                }
              }
              return _results1;
            }).call(this));
          }
          return _results;
        }).call(this);
      };
    }).call(this);
    
    Morris.Bar({
      element: 'category-bar-chart',
      data: [
        { "y": "Performance", "a": 23 },
        { "y": "Maintainability", "a": 106 },
        { "y": "Others", "a": 98 },
        { "y": "Portability", "a": 27 },
        { "y": "Reliability", "a": 87 },
        { "y": "Security", "a": 14 }],
      xkey: 'y',
      ykeys: ['a'],
      labels: ['Violation'],
      xLabelAngle: 43,
      labelTop: true
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.min.js"></script>
    <link href="//cdnjs.cloudflare.com/ajax/libs/morris.js/0.5.1/morris.css" rel="stylesheet" />
    
    <div id="category-bar-chart"></div>