Search code examples
eventschart.jsclickaxis

How to detect click on chart js 3.7.1 axis label?


How to detect click on an axis label with chart.js

In the example bellow, I can only detect click on the graph itself

https://stackblitz.com/edit/ng2-charts-bar-template-qchyz6


Solution

  • You will need to implement a custom plugin that can listen to all the events of the canvas:

    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>