Chart.js 4 基于最低值的线性渐变

问题描述 投票:0回答:1

我遵循

Chart.js
中的标准示例:线性渐变。当我设置选项
beginAtZero: false
时,渐变效果正常。但是,当我设置选项
beginAtZero: true
时,渐变不会考虑最低值。它从图表底部没有数据的地方开始。

如何更改函数以使梯度考虑最低值的位置?

我尝试计算位置:

gradient = ctx.createLinearGradient(0, 
Math.max(...chart.getDatasetMeta(0).data.map(item => item.y)), 0, 
Math.min(...chart.getDatasetMeta(0).data.map(item => item.y)));

但是,当调用函数

getDradient()
时,数据点位置不可用。

请参阅代码笔:https://codepen.io/miloslav/pen/YzdwLOe

javascript chart.js
1个回答
0
投票

使用您的脚本化

borderColor: function(context, opts)
您提取了
chart
、图表实例以及
chartArea
和 画布 2d 上下文为:

const chart = context.chart;
const {ctx, chartArea} = chart;

您还可以找到以下内容:

  • 该数据集使用的y轴的id:
    const yScaleId = opts._proxy.scales.y.id; 
    
    对于具有多个 y 轴的图表,这是严格的方法;实际上,您可能知道 id,在这种情况下,只有默认轴,id 是
    y
  • 实际的 y 尺度对象
       chart.scales[yScaleId]
    
    及其
    min
    max
    值,
    scaleMin
    scaleMax
  • 该数据集的数据数组:
    context.dataset.data
    
    并从中得出数据的最小值和最大值,
    dataMin
    dataMax
  • 有了轴和数据的极值,这是一个简单的 线性关系将给出:
    const fracStart = (dataMin - scaleMin)/(scaleMax - scaleMin),
           fracEnd = (dataMax - scaleMin)/(scaleMax - scaleMin);
    
    这些是在线性垂直渐变定义中应替换
    0
    1
    的数字,以便第一个颜色对应于最小值,最终颜色对应于最大值。

来自您的代码笔的完整代码:

const ctx = document.getElementById('myChart');

let width, height, gradient;
function getGradient(ctx, chartArea, fracStart = 0, fracEnd = 1) {
  const chartWidth = chartArea.right - chartArea.left;
  const chartHeight = chartArea.bottom - chartArea.top;
  if (!gradient || width !== chartWidth || height !== chartHeight) {
    // Create the gradient because this is either the first render
    // or the size of the chart has changed
    width = chartWidth;
    height = chartHeight;
    gradient = ctx.createLinearGradient(0, chartArea.bottom, 0, chartArea.top);
    const fracMid = (fracStart + fracEnd) / 2;
    gradient.addColorStop(fracStart, 'green');
    gradient.addColorStop(fracMid, 'yellow');
    gradient.addColorStop(fracEnd, 'red');
  }

  return gradient;
}

new Chart(ctx, {
  type: 'line',
  data: {
    labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
    datasets: [{
      label: '# of Votes',
      data: [31, 27, 30, 51, 28, 32],
      stepped: true,
      borderWidth: 4,
      borderColor: function(context, opts) {
        const chart = context.chart;
        const {ctx, chartArea} = chart;
        
         // the id of the y scale of this dataset:
        const yScaleId = opts._proxy.scales.y.id; 
        const scaleMin = chart.scales[yScaleId].min,
              scaleMax = chart.scales[yScaleId].max;
        const dataMin = Math.min(...context.dataset?.data ?? [scaleMin]),
              dataMax = Math.max(...context.dataset?.data ?? [scaleMax]);
        const fracStart = (dataMin - scaleMin)/(scaleMax - scaleMin),
              fracEnd = (dataMax - scaleMin)/(scaleMax - scaleMin);

        if (!chartArea) {
          // This case happens on initial chart load
          return;
        }
        return getGradient(ctx, chartArea, fracStart, fracEnd);
      },
    }]
  },
  options: {
    scales: {
      y: {
        beginAtZero: true
      }
    }
  }
});
<div>
  <canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>

codepen 叉子

© www.soinside.com 2019 - 2024. All rights reserved.