如何检测 Chart.js 3.7.1 轴标签的点击事件?

6
2个回答

5

您需要实现一个自定义插件,它可以监听画布的所有事件:

const findLabel = (labels, evt) => {
  let found = false;
  let res = null;

  labels.forEach(l => {
    l.labels.forEach((label, index) => {
      if (evt.x > label.x && evt.x < label.x2 && evt.y > label.y && evt.y < label.y2) {
        res = {
          label: label.label,
          index
        };
        found = true;
      }
    });
  });

  return [found, res];
};

const getLabelHitboxes = (scales) => (Object.values(scales).map((s) => ({
  scaleId: s.id,
  labels: s._labelItems.map((e, i) => ({
    x: e.translation[0] - s._labelSizes.widths[i],
    x2: e.translation[0] + s._labelSizes.widths[i] / 2,
    y: e.translation[1] - s._labelSizes.heights[i] / 2,
    y2: e.translation[1] + s._labelSizes.heights[i] / 2,
    label: e.label,
    index: i
  }))
})));

const plugin = {
  id: 'customHover',
  afterEvent: (chart, event, opts) => {
    const evt = event.event;

    if (evt.type !== 'click') {
      return;
    }

    const [found, labelInfo] = findLabel(getLabelHitboxes(chart.scales), evt);

    if (found) {
      console.log(labelInfo);
    }

  }
}

Chart.register(plugin);

const options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'pink'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'orange'
      }
    ]
  },
  options: {}
}

const ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.7.1/chart.js"></script>
</body>


运行良好。有没有想法将代码适应于使用ng2-charts的Angular项目? - Iznogood1
应该可以在ng2-charts中正常工作,因为我已经在图表对象上全局注册了插件,并且它在每个包装器中都得到支持,因为它直接使用chart.js而不与包装器交互。 - LeeLenalee

-1

使用ng2-charts(chart-js v3.7.1)适配Angular

只需使用Chart.register即可。

例如,将以下函数放入组件的ngOnInit()中:

RegisterPlugin() {
    Chart.register(
      {
        id: 'yAxisCustomClick',
        afterEvent: (chart: Chart<'bar'>, event: {
          event: ChartEvent;
          replay: boolean;
          changed?: boolean | undefined;
          cancelable: false;
          inChartArea: boolean
        }) => {
          const evt = event.event;
          if (evt.type === 'click' && evt.x! < Object.values(chart.scales).filter(s => s.id === 'x')[0].getBasePixel()) {
            const labelIndex = Object.values(chart.scales).filter(s => s.id === 'y')[0].getValueForPixel(evt.y!);
            const label = Object.values(chart.scales).filter(s => s.id === 'y')[0].getTicks()[labelIndex!]?.label;
            if (label) {
              console.log('Do the stuff for', label)
            }
          }
        }
      }
    );
  }

在 Stackblitz 中更新的示例 https://stackblitz.com/edit/ng2-charts-bar-template-qchyz6


这会检测到对条形的点击,而不是标签的点击。 - LeeLenalee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接