【问题标题】:Show bar with zero value in ChartJs v2在 ChartJs v2 中显示零值的条形图
【发布时间】:2017-08-19 20:00:30
【问题描述】:

我想知道有没有办法在 ChartJs(条形图)条中显示零值?

我的意思是这样的:https://jsfiddle.net/vrg5cnk5/16/,所以第二个栏将是零级的蓝色边框。

我已经使用了这个代码:

ticks: {
    beginAtZero: true,
    min: 0,
    suggestedMin: 0
}

但我并不惊讶它不起作用。

提前致谢

【问题讨论】:

标签: bar-chart chart.js


【解决方案1】:

这是在 V3 图表 js 中执行此操作的最简单方法

Chart.defaults.datasets.bar.minBarLength = 5;

【讨论】:

  • 这为我节省了很多麻烦和时间!
【解决方案2】:

只需在数据集中指定minBarLength,以及条形应具有的最小长度(以像素为单位)。见documentation

工作示例:

var $chartCanvas = $('myCanvas');
var barChart = new Chart(myCanvas, {
    type: 'bar',
    data: {
        labels: ['Accepted Answer', 'Top rated answer', 'This Answer'],
        datasets:[{
            data: [0, 3, 10],
            minBarLength: 7,    // This is the important line!
        }]
    },
    options: {
        title: {
            display: true,
            text: 'helpfulness of answers to this questions'
        },
        legend: {
            display: false
        }
    }
});
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<canvas id="myCanvas"></canvas>

【讨论】:

  • 最佳解决方案!很抱歉,我不能多次投票。
  • 这绝对是最简单最实用的解决方案。
【解决方案3】:

深入插件系统后,如果你使用Chart.js >=2.5,你可以写一个插件来实现。这是一个在数据为零时画一条线的例子。

这是我的代码:

const zeroCompensation = {
  renderZeroCompensation: function (chartInstance, d) {
      // get postion info from _view
      const view = d._view
      const context = chartInstance.chart.ctx

      // the view.x is the centeral point of the bar, so we need minus half width of the bar.
      const startX = view.x - view.width / 2
      // common canvas API, Check it out on MDN
      context.beginPath();
      // set line color, you can do more custom settings here.
      context.strokeStyle = '#aaaaaa';
      context.moveTo(startX, view.y);
      // draw the line!
      context.lineTo(startX + view.width, view.y);
      // bam! you will see the lines.
      context.stroke();
  },

  afterDatasetsDraw: function (chart, easing) {
      // get data meta, we need the location info in _view property.
      const meta = chart.getDatasetMeta(0)
      // also you need get datasets to find which item is 0.
      const dataSet = chart.config.data.datasets[0].data
      meta.data.forEach((d, index) => {
          // for the item which value is 0, reander a line.
          if(dataSet[index] === 0) {
            this.renderZeroCompensation(chart, d)
          }
      })
  }
};

这里是如何将插件添加到 Chart.js

var chart1 = new Chart(ctx, {
    plugins: [zeroCompensation]
});

官方文档并不清楚他们的插件API,你可以通过console.log找到你想要的。

【讨论】:

    【解决方案4】:

    2019 年更新

    这可以很容易地完成,如下所示。

    var myChart = new Chart(ctx, {
        ...
        options: {
            ...
            scales: {
                yAxes: [{
                    ticks: {
                        beginAtZero: true
                    }
                }]
            }
        }
    );
    

    您可以在 Chart.js 文档https://www.chartjs.org/docs/latest/中找到它

    【讨论】:

    • 这似乎不起作用。它不画线。
    • @rwwagner90 您是否尝试从 chartjs.org/docs/latest 添加完整对象。我只添加了部分代码来突出显示重要部分 - `ticks: { beginAtZero: true }`
    • 这似乎与问题无关。 beginAtZero 与提问者所寻找的含义不同:“如果为真,如果尚未包含,则比例尺将包含 0。” chartjs.org/docs/latest/axes/cartesian/linear.html
    【解决方案5】:

    我只是偶然发现了这个问题,因为我遇到了类似的问题:我的 Chart.js 图表的类型是“horizo​​ntalBar”并且对于某些数据集(数据集中没有零值)水平条不是从 0 开始,而是从数据集中的最小值开始。

    我试图找出一个解决方案,并在创建图表时在 options 对象中提出了以下条目:

    ticks: {
                      beginAtZero:true,
                      mirror:false,
                      suggestedMin: 0,
                      suggestedMax: 100
    } 
    

    然而,尽管所有帖子都说它是这样工作的,但它并没有按预期工作。 在进一步调查和阅读 Chart.js 文档后,我找到了解决方案。进一步的步骤不起作用的原因是我在documentation 中找到的:

    但是,在条形图中的 x 轴上指定的任何选项都将应用于水平条形图中的 y 轴。

    所以我只是更改了我的选项对象以保存 xAxes 的正确配置并且它起作用了。

    对于那些感兴趣的人,这里是我用于创建 y 轴始终从零开始的水平条形图的整个代码:

    this.chart = new Chart(
        ctx,
        {
            type: 'horizontalBar',
            data: this.data.chartdata,
            options: {
              scales: {
                  xAxes: [{ 
                    stacked: false,
                    ticks: {
                      beginAtZero:true,
                      mirror:false,
                      suggestedMin: 0,
                      suggestedMax: 100
                    } 
                  }],
                  yAxes: [{ 
                    stacked: true
                  }]
              },
              scaleBeginAtZero : true,
              // important here to use () =>
              // to keep the scope of this
              onClick: (e) => {
                var actChart : Chart = this.charts[trialId];
                var element =
                  actChart.getElementAtEvent(e);
    
                }
            }
        }
    );
    

    【讨论】:

      【解决方案6】:

      如果您对此感到困惑,这就是我想出的。这与李金耀的想法相似,但除此之外,您将获得适用于整个栏的单击和悬停事件(工具提示)。 I 值接近 0 但为负数,条形图将显示在 x 轴的负数侧 - 如果您不想这样做,您可以轻松摆脱它。

      const zeroCompensation = {
      id: 'zeroCompensation',
      
      beforeDatasetsDraw: function(chart) {
          const meta = chart.getDatasetMeta(0)
          forEach(meta.data, d => {
              const barHeight = d._view.base - d._view.y;
              if(Math.abs(barHeight) < minBarHeight /* I used value 5 */) {
                  d._view.y = d._view.base - minBarHeight * (Math.sign(barHeight) || 1);
              }
          });
      }};
      

      并将其添加到插件中:

      plugins: [zeroCompensation]
      

      请记住,这将适用于接近 0 的值,而不仅仅是 0。如果您只希望它用于零,您可以将 if 条件的内容更改为:

      chart.config.data.datasets[0].data[index] === 0
      

      这是李瑾瑶在回答中所用的。 希望有帮助。
      编辑:我想强调的是,无论价值观如何传播,此解决方案都有效。如果数据集中有一些高值,则标记为解决方案的答案将无法按预期工作 - 在这种情况下,0.1 将呈现为 0。

      【讨论】:

      • 我使用了您的代码的这种变体: const minBarHeight = 2; export const zeroCompensation = { id: 'zeroCompensation', beforeDatasetsDraw: function(chart: any) { const meta = chart.getDatasetMeta(0) meta.data.forEach( (d:any) => { const barHeight = d._view. base - d._view.y; if(Math.abs(barHeight)
      • 很酷,有人发现它很有用。
      • 确实,它非常适合竖条。当我专门为水平条形图调整它时,我得到了我想要的条形图,但是charts.js 会在一瞬间重新绘制并将其恢复为零宽度。我尝试了所有与绘图相关的生命周期钩子,但它仍然将其重新绘制为零宽度
      【解决方案7】:

      无法配置 chart.js 来执行此操作,但您可以使用 hack 代替。只需将 0 条的值设置为一个非常小的数字,例如 0.1。

      data: [2, 0.1, 3, 1]
      

      这是一个 example 来自你的分支。

      如果您正在使用工具提示,那么您还必须添加一些逻辑,以便该栏的工具提示仍显示值 0。您可以使用 label 回调来做到这一点。

      label: function(tooltipItem, data) {
        var value = data.datasets[0].data[tooltipItem.index];
        var label = data.labels[tooltipItem.index];
      
        if (value === 0.1) {
          value = 0;
        }
      
        return label + ': ' + value + ' %';
      }
      

      这是一个example 将所有内容放在一起。

      【讨论】:

      • 我正在为自定义工具提示使用回调,代码:jsfiddle.net/xe97vca6/3 回调:{ label: function(tooltipItem, data) { var value = data.datasets[0].data[tooltipItem.index] ; var label = data.labels[tooltipItem.index];返回标签+':'+值+'%'; } } 如果你能告诉我如何自定义它以显示 0 - 那就太好了!
      • 谢谢,效果很好 - 当然你必须操纵值和边框宽度以获得最佳结果,但这没问题
      • 我找到了需要操作核心库的解决方案——它也可以工作,但修改了 Chart.js 源代码——也许有人想选择这个github.com/chartjs/Chart.js/issues/3915
      • 这可以通过 options 使用最新版本的 Chart.js 轻松完成。在这里找到答案stackoverflow.com/a/58002951/4842112
      • 检查来自@talz 的答案,它就像一个魅力!,必须将最小大小放入数据集中:stackoverflow.com/a/65796691/5810474
      猜你喜欢
      • 2023-03-12
      • 1970-01-01
      • 2013-07-21
      • 1970-01-01
      • 2019-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-04
      相关资源
      最近更新 更多