ChartJS 不同的背景渐变取决于数据(折线图)

2022-01-22 00:00:00 ruby-on-rails javascript chart.js

我正在尝试使用 ChartJS 折线图创建看起来像这样的东西.我的顶部渐变可以按我的意愿工作,但当我的数据值低于 0 时,我找不到让底部渐变发生变化的方法.

I am trying to create something that looks like this using ChartJS line graph. I've got the top gradient working as I want, I just cannot find a way to get the bottom gradient to change when my data value is below 0.

我尝试使用基于我的数据的不同背景颜色的数组,并且我尝试使用插件 beforeDraw 来更改背景颜色(它将它们全部更改为相同的颜色).

I've tried using an array of different background colors based on my data and I have tried using plugin beforeDraw to change the background color (it changed them all to the same color).

推荐答案

Chart.js 问题 #3071 折线图的多种填充颜色 似乎符合您的目标.官方回应是使用 CanvasGradient.幸运的是,berosoboy"发布了一个内联插件来做这.下面包括一个工作示例.我稍作修改以删除对 window.myColors 的引用.

Chart.js issue #3071 Multiple fill colors for line chart seems to match your objective. The official response is to use a CanvasGradient. Fortunately, 'berosoboy' has posted an inline plugin to do this. A working example is included below. I've modified it slightly to remove references to window.myColors.

let posColour = 'rgba(0, 255, 0, .1)',
  negColour = 'rgba(255, 0, 0, .1)',
  myBarChart = new Chart(document.getElementById('chart'), {
    type: 'line',
    data: {
      labels: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
      datasets: [{
        label: 'Series1',
        data: [1, -1, 1, -1, 1, -1, 1, -1, 1, -1]
      }]
    },
    options: {
      maintainAspectRatio: false
    },
    // source: https://github.com/chartjs/Chart.js/issues/3071#issuecomment-371001496
    plugins: [{
      beforeRender: function(c, options) {
        var dataset = c.data.datasets[0];
        var yScale = c.scales['y-axis-0'];
        var yPos = yScale.getPixelForValue(0);

        var gradientFill = c.ctx.createLinearGradient(0, 0, 0, c.height);
        gradientFill.addColorStop(0, posColour);
        gradientFill.addColorStop(yPos / c.height - 0.01, posColour);
        gradientFill.addColorStop(yPos / c.height + 0.01, negColour);
        gradientFill.addColorStop(1, negColour);

        var model = c.data.datasets[0]._meta[Object.keys(dataset._meta)[0]].$filler.el._model;
        model.backgroundColor = gradientFill;
      }
    }]
  });

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.min.js"></script>
<canvas id="chart"></canvas>

Chart.js v3.x 支持本机:

Chart.js v3.x supports this natively:

let posColour = 'rgba(0, 255, 0, .1)',
  negColour = 'rgba(255, 0, 0, .1)',
  myBarChart = new Chart(document.getElementById('chart'), {
    type: 'line',
    data: {
      labels: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
      datasets: [{
        label: 'Series1',
        data: [1, -1, 1, -1, 1, -1, 1, -1, 1, -1],
        fill: {
          target: 'origin',
          above: posColour,
          below: negColour
        }
      }]
    },
    options: {
      maintainAspectRatio: false
    }
  });

<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.6.0/chart.min.js"></script>
<canvas id="chart"></canvas>

相关文章