This is probably one of the more useful (AND SIMPLE) features missing from Chart.js. My code should mostly work already - if you don't have multiple labels/datasets - which is what I'm trying to figure out. We just need to iron out the last few details, and we'll have an awesome new feature.
For context, I'm using a line chart, and I'm on version 3.5.1 of Chart.js, but this should also work for the newest version (4.2.1 as of Feb 2023)
We can use myChart.getActiveElements(); to get the currently selected element.
And we can use this, for example, to programmatically show a tooltip...
myChart.tooltip.setActiveElements([{ datasetIndex: 1, index: 1 }]);
myChart.update();
So it really shouldn't be that difficult to navigate through the chart.
Here's the code that I'm tinkering with.
const myChart = Chart.getChart("myChart"); // make sure to replace the "myChart"
var active_element;
document.addEventListener('keydown', event => {
active_element = myChart.getActiveElements();
if ( ! active_element.length ) {
myChart.setActiveElements([{ datasetIndex: 0, index: 0 }]);
myChart.tooltip.setActiveElements([{ datasetIndex: 0, index: 0 }]);
myChart.update();
active_element = myChart.getActiveElements();
}
const active = active_element[0];
const dataset = myChart.data.datasets[active.datasetIndex];
const data = dataset.data;
let index = active.index;
if ( event.code === 'ArrowLeft' ) {
index = index > 0 ? index - 1 : data.length - 1;
} else if ( event.code === 'ArrowRight' ) {
index = index < data.length - 1 ? index + 1 : 0;
}
console.log('active', active.datasetIndex);
console.log('index ', index);
myChart.setActiveElements([{ datasetIndex: active.datasetIndex, index }]);
myChart.tooltip.setActiveElements([{ datasetIndex: active.datasetIndex, index }]);
myChart.update();
});
The main issue that I'm having trouble with, is when you have more than one label for each x-axis point (multiple datasets).
Another obstacle that we'll need to overcome is when you have your mouse on the chart, you will always have the same active chartElement... Currently, having your mouse on the chart stops it from working. So instead we don't allow that, and we simply trigger the 0th element from the start, store the value, and use that value for future updates. This is fine for now, but ultimately should be solved.
This is a pretty fundamental accessibility feature that I think we're all surprised isn't available by default. People have been asking for it since at least 2016 as you can see here: https://github.com/chartjs/Chart.js/issues/1976
I'm so close to having a working solution. This code should run on any line chart, you just need to edit the first line of code const myChart = Chart.getChart("your_chart_here");
Let's do this!!
I wrote a library, Chart2Music, that helps provide keyboard navigation and sonification for keyboard-only and screen reader users.
Since I love using chart.js, I also built a chart.js plugin for it. It's called chartjs-plugin-chart2music, and is still in beta.
You can get the accessibility support simply by registering the plugin.
import Chart from "chart.js/auto";
import chartjs2music from "chartjs-plugin-chart2music";
// Register the plugin globally
Chart.register(chartjs2music);
If you want to play with it, here's a codepen example with keyboard navigation and sonification: https://codepen.io/chart2music/full/YzaVxPK
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With