You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何对齐TChart左右纵轴的Ticks与Grids?双折线轴对齐

解决TChart双纵轴刻度与网格对齐的问题

嘿,我太懂你这个困扰了——双Y轴的网格线错位真的很影响图表的可读性,而且你按刻度数量计算右侧增量的思路其实没问题,但为啥没生效呢?核心原因是只匹配刻度数量,没匹配刻度的实际屏幕位置,两侧数值范围的比例如果不是整数倍,就算刻度数一样,刻度对应的垂直位置还是对不上。

给你分享一个更可靠的方案:基于左侧轴的刻度屏幕位置,反向计算右侧轴对应的刻度值,强制让两侧刻度线在同一水平线上,这样网格自然就对齐了。

具体实现代码

private void AlignAxes()
{
    // 先确保左侧轴完成刻度计算(自动/手动设置都适用)
    tChart1.Axes.Left.CalculateMinMax();

    // 收集左侧轴的所有刻度值(包含最小、最大值和中间增量刻度)
    List<double> leftTickValues = new List<double>();
    double currentLeftTick = tChart1.Axes.Left.Minimum;
    
    while (currentLeftTick <= tChart1.Axes.Left.Maximum + double.Epsilon)
    {
        leftTickValues.Add(currentLeftTick);
        currentLeftTick += tChart1.Axes.Left.CalcIncrement;
    }

    // 把左侧每个刻度的屏幕位置,转换成右侧轴对应的数值
    List<double> rightTickValues = new List<double>();
    foreach (double leftVal in leftTickValues)
    {
        // 获取左侧刻度对应的屏幕Y坐标
        int screenY = tChart1.Axes.Left.CalcYPosValue(leftVal);
        // 将屏幕坐标反向转换成右侧轴的数值
        double rightVal = tChart1.Axes.Right.CalcPosPoint(screenY);
        rightTickValues.Add(rightVal);
    }

    // 配置右侧轴使用自定义刻度
    tChart1.Axes.Right.Automatic = false;
    tChart1.Axes.Right.CustomTicks.Clear();
    
    foreach (double tickVal in rightTickValues)
    {
        CustomTick customTick = new CustomTick(tChart1.Axes.Right);
        customTick.Value = tickVal;
        customTick.Visible = true;
        customTick.Tick.Visible = true; // 显示刻度线
        customTick.Label.Visible = true; // 显示刻度标签
        tChart1.Axes.Right.CustomTicks.Add(customTick);
    }

    // 确保右侧网格线基于自定义刻度显示
    tChart1.Axes.Right.Grid.Visible = true;
}

为什么这个方法有效?

之前的代码只是把右侧范围按左侧刻度数量均分,但忽略了数值到屏幕坐标的映射关系。比如左侧是0-100(增量20),右侧是0-70,按5个刻度算增量14,此时左侧20对应的屏幕位置,和右侧14对应的位置完全不同,网格自然错位。

而这个方案是:

  1. 先拿到左侧每个刻度的垂直屏幕位置
  2. 把这个位置“映射”到右侧轴,算出对应的数值
  3. 让右侧轴只在这些数值位置显示刻度和网格

这样就能保证两侧的刻度线、网格线完全对齐,不管两侧数值范围差异多大。

注意事项

  • 建议在图表数据更新后、绘制前调用这个方法,比如在AfterDraw事件或者数据加载完成后执行
  • 如果左侧轴是手动设置的固定刻度,直接用你手动定义的刻度值即可,不用自动收集
  • 加入double.Epsilon是为了处理浮点精度问题,避免漏掉最大值刻度

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

火山引擎 最新活动