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

如何在react-chart-js 2中关联散点图的双坐标轴?

解决react-chartjs-2散点图X轴与Y轴0刻度对齐问题

问题背景

使用react-chartjs-2 v5.2.0(依赖ChartJS v4.1.2)实现散点图,需求是让X轴固定在Y轴0刻度的位置,同时Y轴根据数据自动调整范围。但配置后出现Y轴偏移,0刻度跑到X轴上方的问题。

已尝试方案

  • 设置Y轴min/max固定范围,但X轴始终停留在图表底部,无法与Y轴0刻度对齐;
  • 编写自定义插件尝试绘制中间X轴,但未实现预期效果,插件代码如下:
const plugin = {
  id: 'middleAxis',
  beforeDraw(chart) {
    const {ctx, scales} = chart;
    const yAxis = scales.y;
    const xAxis = scales.x;
    const zeroPosition = yAxis.getPixelForValue(0);
    const labelItems = xAxis.getLabelItems();
    ctx.save();
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.moveTo(xAxis.left, zeroPosition);
    ctx.lineTo(xAxis.right, zeroPosition)
    ctx.stroke();
    for (const item of labelItems) {
      const {font, label, options} = item;
      const {strokeWidth, strokeColor, textAlign, textBaseline, translation} = options;
      const x = translation[0];
      const y = zeroPosition + font.lineHeight;
      ctx.beginPath();
      ctx.font = font.string;
      ctx.textAlign = textAlign;
      ctx.textBaseline = textBaseline;
      ctx.lineWidth = strokeWidth;
      ctx.strokeStyle = strokeColor;
      ctx.fillText(label, x, y);
      ctx.fill();
    }
    ctx.restore();
  }
};

export const options5 = {
  elements: {
    line: {
      tension: 0.3,
    },
  },
  scales: {
    x: {
      display: false,
      ticks: {
        display: true,
      },
      grid: {
        drawBorder: false,
        display: false,
      },
    },
  },
  responsive: true,
  maintainAspectRatio: false,
  plugins: [plugin],
};

解决方案

核心思路:隐藏原生X轴,通过自定义插件在Y轴0刻度的像素位置绘制X轴及刻度;同时让Y轴自动适配数据范围,确保0刻度位置随数据动态调整。

修改后的自定义插件

const middleXAxisPlugin = {
  id: 'middleXAxis',
  beforeDraw(chart) {
    const { ctx, scales } = chart;
    const yAxis = scales.y;
    const xAxis = scales.x;
    
    // 获取Y轴0值对应的像素坐标
    const zeroYPosition = yAxis.getPixelForValue(0);
    
    // 绘制与Y轴0刻度对齐的X轴线
    ctx.save();
    ctx.beginPath();
    ctx.lineWidth = 1;
    ctx.strokeStyle = xAxis.options.ticks.color || '#ccc';
    ctx.moveTo(xAxis.left, zeroYPosition);
    ctx.lineTo(xAxis.right, zeroYPosition);
    ctx.stroke();
    
    // 绘制X轴刻度标签
    const labelItems = xAxis.getLabelItems();
    ctx.font = xAxis.options.ticks.font.string;
    ctx.textAlign = 'center';
    ctx.textBaseline = 'top';
    ctx.fillStyle = xAxis.options.ticks.color || '#666';
    
    labelItems.forEach(item => {
      const x = item.translation[0];
      // 标签放在X轴下方5px,避免与轴线重叠
      ctx.fillText(item.label, x, zeroYPosition + 5);
    });
    
    ctx.restore();
  }
};

最终图表配置

export const options5 = {
  elements: {
    line: {
      tension: 0.3,
    }
  },
  scales: {
    x: {
      display: false, // 隐藏原生X轴
      grid: {
        display: false,
        drawBorder: false
      },
      ticks: {
        display: false
      }
    },
    y: {
      display: true,
      // 移除beginAtZero,让Y轴自动适配数据范围
      ticks: {
        display: true
      },
      grid: {
        display: false,
        drawBorder: false
      }
    }
  },
  responsive: true,
  maintainAspectRatio: false,
  plugins: {
    legend: false,
    showLine: true
  },
  // 加载自定义插件
  plugins: [middleXAxisPlugin]
};

关键说明

  1. 移除Y轴的beginAtZero: true配置,让Y轴根据数据自动计算上下限,确保0刻度位置随数据动态调整;
  2. 隐藏原生X轴,通过插件在Y轴0值对应的像素位置绘制自定义X轴,保证两者始终对齐;
  3. 插件复用原生轴的样式配置(颜色、字体),保证图表风格统一;
  4. 调整刻度标签位置,避免与X轴线重叠,提升可读性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 10:40:37