如何在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] };
关键说明
- 移除Y轴的
beginAtZero: true配置,让Y轴根据数据自动计算上下限,确保0刻度位置随数据动态调整; - 隐藏原生X轴,通过插件在Y轴0值对应的像素位置绘制自定义X轴,保证两者始终对齐;
- 插件复用原生轴的样式配置(颜色、字体),保证图表风格统一;
- 调整刻度标签位置,避免与X轴线重叠,提升可读性。
内容的提问来源于stack exchange,提问作者Feyto
相关产品推荐
相关产品推荐

