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

Chart.js中实现跟随数据曲线的垂直线性渐变问题

Chart.js 实现跟随曲线的渐变填充

问题描述

在Chart.js中创建普通垂直渐变并不复杂,但这类渐变是从固定点向下延伸的,导致低数值的数据点无法显示出红至透明的渐变效果。我编写的代码能设置渐变起始点,但没法实现渐变跟随数据点移动并向下淡出的效果,当前效果不符合预期,希望能让渐变跟随曲线变化,现有代码如下:

当前代码

plugins: [
      {
        afterLayout: (chart) => {
          let ctx = chart.ctx;
          ctx.save();
          let xAxis = chart.scales['x'];
          let yAxis = chart.scales['y'];
          let gradient = ctx.createLinearGradient(0, yAxis.top, 0, yAxis.bottom);

          chart.data.datasets.forEach((dataSet) => {
            let color;
            const data = dataSet.data;
            data.forEach((v, index) => {
              let x = xAxis.getPixelForTick(index);
              const y = yAxis.getPixelForTick(index);
              let offset = (y - yAxis.top) / (yAxis.bottom - yAxis.top);
              offset = Math.max(0, Math.min(1, offset));
              let alpha = 1 - offset;
              let rgbValues = dataSet.borderColor.toString().match(/\d+/g);
              let color = `rgba(${rgbValues[0]}, ${rgbValues[1]}, ${rgbValues[2]}, ${alpha})`;
              if (color) {
                gradient.addColorStop(offset, color);
              }
            });
            dataSet.backgroundColor = gradient;
            ctx.restore();
          });
        },
        id: '',
      },
    ],

解决方案

当前代码的问题在于使用了全局垂直渐变,且错误通过刻度坐标而非数据点真实位置计算渐变,要实现跟随曲线的渐变填充,可按以下方式修改:

修改后的代码

plugins: [
  {
    beforeDraw: (chart) => {
      const ctx = chart.ctx;
      const xAxis = chart.scales['x'];
      const yAxis = chart.scales['y'];

      chart.data.datasets.forEach((dataset, datasetIndex) => {
        const meta = chart.getDatasetMeta(datasetIndex);
        if (!meta.hidden) {
          // 创建从Y轴顶部到底部的渐变容器
          const gradient = ctx.createLinearGradient(0, yAxis.top, 0, yAxis.bottom);
          const rgb = dataset.borderColor.match(/\d+/g);
          
          // 遍历每个数据点,根据实际位置设置渐变停止点
          dataset.data.forEach((value, index) => {
            const point = meta.data[index];
            const y = point.y;
            // 计算数据点在Y轴的相对位置(0为顶部,1为底部)
            const offset = (y - yAxis.top) / (yAxis.bottom - yAxis.top);
            // 从数据点位置开始向下,透明度逐渐降为0
            const alpha = 1 - Math.max(0, Math.min(1, offset));
            gradient.addColorStop(offset, `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, ${alpha})`);
          });
          // 在Y轴底部添加完全透明的颜色,确保渐变自然淡出
          gradient.addColorStop(1, `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]}, 0)`);
          dataset.backgroundColor = gradient;
        }
      });
    },
    id: 'gradient-follow-curve'
  }
]

关键修改说明

  • 改用beforeDraw钩子:确保每次绘制图表前重新计算渐变,适配数据更新或图表缩放场景。
  • 获取数据点真实坐标:通过chart.getDatasetMeta(datasetIndex).data[index].y拿到数据点的实际Y轴像素位置,而非刻度位置。
  • 优化渐变逻辑:在Y轴底部强制添加完全透明的颜色停止点,保证渐变从数据点位置向下自然淡出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 23:12:48