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

Chart.js:点击图例时刷新右侧Y轴刻度步长的问题

解决Chart.js图例点击时右侧Y轴步长不更新的问题

我明白你遇到的困扰了——点击图例后图表确实刷新了,但右侧Y轴的步长完全没变化,对吧?这是因为你只是修改了局部变量stepSize,但Chart.js的图表配置并没有被实际更新,所以刻度自然不会跟着调整。咱们来一步步修复这个问题:

问题根源

你在图例点击事件里修改的stepSize只是drawChart函数内部的局部变量,并没有同步到图表实例的配置对象中。Chart.js在调用update()时,只会读取当前实例options里的配置,所以单纯修改局部变量根本不会影响到图表的显示。

解决方案

在图例的onClick回调里,我们需要直接操作图表实例的配置:

  • 通过this.chart获取当前图表实例(回调里的this指向图例控制器)
  • 定位到右侧Y轴的配置项,直接修改它的ticks.stepSize
  • 同步调整Y轴的max和min,确保双Y轴刻度范围始终一致
  • 最后调用chart.update()让新配置生效

修改后的代码片段

把你原来的legend.onClick部分替换成下面的代码:

onClick: function(e, legendItem) {
  // 获取当前图表实例
  const chart = this.chart;
  // 找到右侧Y轴(通过position属性定位)
  const rightYAxis = chart.options.scales.yAxes.find(axis => axis.position === 'right');
  
  // 这里可以根据需求切换步长,示例中改为0.01
  // 如果需要根据点击的图例项动态调整,可结合legendItem.datasetIndex判断
  rightYAxis.ticks.stepSize = 0.01;
  
  // 同步更新max/min,保持双Y轴范围一致(可根据你的业务逻辑调整)
  rightYAxis.ticks.max = parseFloat(maxY.toFixed(2));
  rightYAxis.ticks.min = parseFloat(minY.toFixed(2));
  
  // 触发图表更新,让配置生效
  chart.update();
}

完整优化后的绘制函数

为了确保双Y轴始终保持一致的刻度范围,我还调整了左侧Y轴的配置,让它和右侧共享相同的max和min:

function drawChart(pointsArray, curveFeatures) { 
  let minX = parseFloat(curveFeatures.minX); 
  let minY = parseFloat(curveFeatures.minY); 
  let maxX = parseFloat(curveFeatures.maxX); 
  let maxY = parseFloat(curveFeatures.maxY); 
  let stepResult = parseInt(curveFeatures.stepResult); 
  let startX = parseFloat(curveFeatures.startX); 
  let endX = parseFloat(curveFeatures.endX); 
  let upperLimit = parseFloat(curveFeatures.upperLimit); 
  let lowerLimit = parseFloat(curveFeatures.lowerLimit); 
  let stepSize; 
  let borderColour; 
  let backgroundColour; 

  if (stepResult === 1) { 
    stepSize = 0.5; 
    maxY = parseFloat(maxY.toFixed(2)) + stepSize; 
    minY = parseFloat(minY.toFixed(2)) - stepSize; 
    borderColour = "rgba(1, 165, 15, 1)"; 
    backgroundColour = "rgba(1, 165, 15, 0.2)"; 
  } else { 
    stepSize = 0.01; 
    maxY = parseFloat(maxY.toFixed(2)); 
    minY = parseFloat(minY.toFixed(2)); 
    borderColour = "rgba(252, 45, 45, 1)"; 
    backgroundColour = "rgba(252, 45, 45, 0.2)"; 
  } 

  let ctx = document.getElementById("myChart").getContext("2d"); 
  let myChart = new Chart(ctx, { 
    type: "line", 
    data: { 
      datasets: [{ 
        label: "Press Signal", 
        cubicInterpolationMode: "monotone", 
        fill: false, 
        borderWidth: 5, 
        radius: 1, 
        borderColor: borderColour, 
        backgroundColor: backgroundColour, 
        pointBorderColor: borderColour, 
        pointBackgroundColor: backgroundColour, 
        data: pointsArray 
      }, { 
        label: "Evaluation Windows", 
        cubicInterpolationMode: "monotone", 
        fill: true, 
        borderWidth: 2, 
        radius: 2, 
        borderColor: "rgb(94, 233, 255, 1)", 
        backgroundColor: "rgb(94, 233, 255, 0.2)", 
        pointBorderColor: "rgb(94, 233, 255, 1)", 
        pointBackgroundColor: "rgb(94, 233, 255, 0.2)", 
        data: [{ x: startX, y: lowerLimit }, { x: startX, y: upperLimit }, { x: endX, y: upperLimit }, { x: endX, y: lowerLimit }, { x: startX, y: lowerLimit }] 
      }] 
    }, 
    options: { 
      responsive: true, 
      maintainAspectRatio: true, 
      animation: { duration: 2000 }, 
      layout: { 
        padding: { left: 50, right: 50, top: 50, bottom: 10 } 
      }, 
      title: { 
        display: true, 
        text: "Press Signal", 
        fontSize: 30, 
        padding: 20 
      }, 
      legend: { 
        labels: { fontSize: 16 }, 
        onClick: function(e, legendItem) { 
          // 获取图表实例
          const chart = this.chart;
          // 定位右侧Y轴
          const rightYAxis = chart.options.scales.yAxes.find(axis => axis.position === 'right');
          
          // 切换步长为0.01(可根据业务逻辑动态调整)
          rightYAxis.ticks.stepSize = 0.01;
          // 同步max/min,保持双Y轴范围一致
          rightYAxis.ticks.max = parseFloat(maxY.toFixed(2));
          rightYAxis.ticks.min = parseFloat(minY.toFixed(2));
          
          // 更新图表
          chart.update();
        } 
      }, 
      scales: { 
        xAxes: [{ 
          display: true, 
          type: "linear", 
          position: "bottom", 
          ticks: { fontSize: 14 }, 
          scaleLabel: { 
            display: true, 
            fontSize: 16, 
            fontColor: "black", 
            labelString: "Position (Abs.) [mm]" 
          } 
        }], 
        yAxes: [{ 
          display: true, 
          type: "linear", 
          position: "left", 
          ticks: { 
            fontSize: 14,
            max: maxY,
            min: minY
          }, 
          scaleLabel: { 
            display: true, 
            fontSize: 16, 
            fontColor: "black", 
            labelString: "Force [kN]" 
          }
        }, { 
          display: true, 
          type: "linear", 
          position: "right", 
          ticks: { 
            fontSize: 14, 
            beginAtZero: false, 
            max: maxY, 
            min: minY, 
            stepSize: stepSize 
          }, 
          afterTickToLabelConversion: function(scaleInstance) { 
            if (stepResult === 1) { 
              scaleInstance.ticks[0] = null; 
              scaleInstance.ticks[scaleInstance.ticks.length - 1] = null; 
              scaleInstance.ticksAsNumbers[0] = null; 
              scaleInstance.ticksAsNumbers[scaleInstance.ticksAsNumbers.length - 1] = null; 
            } 
          } 
        }] 
      } 
    } 
  }); 
}

额外提示

  • 如果需要根据图例的显示/隐藏状态动态切换步长,可以在onClick里通过legendItem.datasetIndex找到对应的数据集,判断它的hidden属性,再调整步长。
  • 调用chart.update()时,可以传入{duration: 0}参数关闭动画,让刻度即时更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:47:57