You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用Morris.js为零值选项显示细线条条形?

如何在Morris.js条形图中显示零值的细线条条形?

我正在用Morris.js展示图表数据,希望每个选项都显示条形,哪怕数值是零。目前图表里「HIV Instant」对应的21-25岁和26-30岁年龄组数值为0,但没有显示对应的条形。请问怎么给这类零值结果显示细线条样式的条形?这在Morris.js里可行吗?我已经查过条形图文档、谷歌和Stack Overflow,但没找到相关方案,恳请帮助。

我的图表生成代码如下:

// break up the object
var age_barParts = [];
$.each( results_by_age_chart, function(key , val){
 age_barParts.push({
 'test': key,
 'u16': val['u16'],
 '16-20': val['16-20'],
 '21-25': val['21-25'],
 '26-30': val['26-30'],
 '31-49': val['31-49'],
 '50+': val['50+']
 });
});
//build the graph
var age_bar = Morris.Bar({
 element: 'age_bar',
 data: age_barParts,
 xkey: ['test'],
 ykeys: ['u16', '16-20', '21-25', '26-30', '31-49', '50+'],
 labels: ["Under 16s", "16 to 20", "21 to 25", "26 to 30", "31 to 49", "Over 50s"],
 barColors: color_array,
 hideHover: 'auto',
 resize: 'true',
 gridTextSize: 16,
 gridTextColor: '#5cb85c',
 xLabelAngle: '70',
 resize: true,
 padding: 40
});

解决方案:自定义零值条形的渲染

好问题!Morris.js默认确实会跳过数值为0的条形渲染,但我们可以通过两种可靠的方式实现你要的细线条效果:

方法1:修改Morris.js核心绘制逻辑(最彻底)

直接调整Morris.js源码中drawBar函数的判断逻辑,让它即使遇到0值也绘制细线条:

  1. 找到Morris.js文件中Bar图表的drawBar方法(通常在Morris.Bar.prototype.drawBar位置)
  2. 找到类似这样的判断代码:
    if (y === 0) {
      return; // 原逻辑直接跳过绘制
    }
    
  3. 替换成以下代码,实现零值细线条:
    var isZero = (y === 0);
    var barWidth = this.barWidth();
    var x = this.left + this.cols * barWidth + this.barGap() * this.cols;
    // 零值条形紧贴x轴,高度设为1px
    var yPos = isZero ? this.yOrigin : this.transY(y);
    var height = isZero ? 1 : Math.abs(this.transY(y) - this.yOrigin);
    
    // 绘制条形:零值用灰色细线条,正常值保持原有样式
    this.raphael.rect(x, yPos, barWidth, height)
      .attr('fill', isZero ? '#cccccc' : color)
      .attr('stroke', isZero ? '#999999' : 'none')
      .attr('stroke-width', isZero ? 1 : 0);
    

这样修改后,所有0值都会显示成1px高的细条形,你可以根据需求调整颜色、高度甚至改成虚线(添加.attr('stroke-dasharray', '5,5')即可)。

方法2:用postRender事件手动添加(无需改源码)

如果不想修改Morris.js源码,可以利用图表的postRender回调,在图表渲染完成后手动绘制零值的细线条:

修改你的图表初始化代码,添加postRender选项:

var age_bar = Morris.Bar({
  element: 'age_bar',
  data: age_barParts,
  xkey: ['test'],
  ykeys: ['u16', '16-20', '21-25', '26-30', '31-49', '50+'],
  labels: ["Under 16s", "16 to 20", "21 to 25", "26 to 30", "31 to 49", "Over 50s"],
  barColors: color_array,
  hideHover: 'auto',
  resize: true,
  gridTextSize: 16,
  gridTextColor: '#5cb85c',
  xLabelAngle: 70,
  padding: 40,
  // 添加postRender回调
  postRender: function() {
    var chart = this;
    var barWidth = chart.barWidth();
    var barGap = chart.barGap();
    var yOrigin = chart.yOrigin; // x轴的y坐标

    // 遍历每一行数据
    chart.data.forEach(function(row, rowIndex) {
      // 遍历每个年龄组的ykey
      chart.options.ykeys.forEach(function(ykey, colIndex) {
        var value = row[ykey];
        if (value === 0) {
          // 计算零值条形的x坐标
          var x = chart.left + colIndex * barWidth + barGap * colIndex;
          // 绘制1px高的细线条
          chart.raphael.rect(x, yOrigin, barWidth, 1)
            .attr('fill', '#cccccc')
            .attr('stroke', '#999999')
            .attr('stroke-width', 1);
        }
      });
    });
  }
});

注意事项

  • 方法2需要确保你的Morris.js版本在v0.5及以上(postRender事件从该版本开始支持)
  • 两种方法都可以根据需求自定义细线条的样式,比如调整颜色、高度、是否虚线等
  • 如果使用方法1,建议将修改后的Morris.js保存为自定义版本,避免后续官方版本升级覆盖你的修改

内容的提问来源于stack exchange,提问作者Sam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 07:12:31