如何使用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值也绘制细线条:
- 找到Morris.js文件中Bar图表的
drawBar方法(通常在Morris.Bar.prototype.drawBar位置) - 找到类似这样的判断代码:
if (y === 0) { return; // 原逻辑直接跳过绘制 } - 替换成以下代码,实现零值细线条:
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
相关产品推荐
相关产品推荐

