How to create a custom keyboard navigation chart

A picture with a line chart and a play button to symbolise a keyboard navigation

In this tutorial, I will explore how to create a custom keyboard navigation chart with the sonification module. The chart allows you to play a chart and navigate it using keyboard controls, enhancing accessibility and providing an interactive experience. The final result is featured on the demo chart below:

Sonification is the process of translating data into sound, allowing users to perceive and understand data through audio feedback. In this demo, the users can perceive the unemployment rate for three countries Sweden, Japan and USA during the last 20 years from 2002 to 2022.

Let’s see how to create such a chart with 5 steps:

Step 1: Modules

To create a sonification chart, you have to add at least the following modules: Highcharts sonification, and accessibility:

<script src="https://code.highcharts.com/highcharts.js"></script>
<script src="https://code.highcharts.com/modules/data.js"></script>
<script src="https://code.highcharts.com/modules/series-label.js"></script>
<script src="https://code.highcharts.com/modules/sonification.js"></script>
<script src="https://code.highcharts.com/modules/accessibility.js"></script>

Step 2: Accessibility HTML elements

This following HTML elements are used to improve the accessibility experience:

<figure class="highcharts-figure">
  <div id="top">
    <div id="title">
      <h1>Unemployment rate last 20 years</h1>
      <p>Shown in percent of labor force</p>
    </div>
    <button id="sonify">Play chart</button>  
  </div>
  <div id="controls" role="application" tabindex="0" aria-label="Audio chart">
    Press ....
  </div>
  <div id="container"></div>
  <p class="highcharts-description">This demo. ...</p>
</figure>

The figure element with the class highcharts-figure is used to organize and describe a chart for users who rely on screen readers or other assistive devices:

  • The div element with the id="title" serves to convey the chart’s context with the title and subtitle.
  • The button element with the id="sonify" is an accessible control that guide users to interact with the chart’s audio features.
  • These next div elements are equipped with attributes and class such as role, tabindex, aria-label, and highcharts-description to provide keyboard navigation instructions.
  • Now, the modules and the HTML elements are added, let’s check the code needed to get the sonification working. There are three main sections:

    • Sonification configuration
    • Keyboard navigation
    • Sonification mode

    Step 3: Sonification configuration

    The sonification object contains various settings to specify the duration of the sonification process, delays between series, the default instrument, and the spoken series names at the start of each series:

    sonification: {
      duration: 27000,
      afterSeriesWait: 1200,
      defaultInstrumentOptions: {
        instrument: 'basic2',
        mapping: {
          playDelay: 500
        }
      },
      // Speak the series name at beginning of series
      globalTracks: [{
        type: 'speech',
        mapping: {
          text: '{point.series.name}',
          volume: 0.4,
          rate: 2
        },
        // Active on first point in series only
        activeWhen: function(e) {
          return e.point && !e.point.index;
        }
      }]
    },

    Let’s break down the code:

    • duration: This setting specifies the total duration (in milliseconds) for the sonification process.
    • afterSeriesWait: This setting determines the delay (in milliseconds) between the completion of one series and the start of the next series during sonification.
    • defaultInstrumentOptions: This object defines default options for the musical instrument used in sonification, and their mappings to the data
    • globalTracks: This object defines global audio tracks that will be played during the sonification process. These tracks are not related to the data, but play in the background. Here I use a global track to speak the series name, but by using the option activeWhen, it will be only announced at the beginning of each series.

    Step 4: Keyboard navigation

    // Handle the keyboard navigation
    document.getElementById('controls').onkeydown = function (e) {...}

    This section of the code handles keyboard navigation and interaction with a chart. It defines a series of actions to be taken in response to different keyboard events. It allows users to control playback, explore data points and series, and hear spoken descriptions of the data using their keyboard inputs.

    Let’s break down the code:

    • document.getElementById('controls').onkeydown attaches an event handler for the keydown event to the HTML element with the id controls.
    • let lastPlayed;: This variable is declared to keep track of the last data point played during sonification.
    • The line of code speaker = new .. initializes a SonificationSpeaker object, which allows us to manually output speech during the sonification. The speaker is configured with a volume of 0.4 (moderate volume) and a speech rate of 2 (double the normal speed).
    • The function onSinglePointPlayed(e) { ... } is called when an individual data point is played during sonification. It takes an event object e as a parameter, which contains information about the played point. Inside the function, it extracts the first played point and uses the SonificationSpeaker to announce the point’s value description along with the series name.
      • Here is how to handle different keyboard events:

      • If the left or right arrow keys are pressed
        (e.key === 'ArrowLeft' or e.key === 'ArrowRight')

        , it triggers the sonification to play adjacent points in the chart based on the arrow key pressed, and it calls the onSinglePointPlayed function.

      • If the up or down arrow keys are pressed
        (e.key === 'ArrowUp' or e.key === 'ArrowDown')

        , it triggers the sonification to play adjacent series based on the arrow key pressed, and it calls the onSinglePointPlayed function. It also speaks the name of the new series if it’s not the first point.

      • If the spacebar is pressed (e.key === ' '), it toggles sonification on or off by calling chart.toggleSonify(false).
      • If the Home or End keys are pressed
        (e.key === 'Home' or e.key === 'End')

        , it plays the first or last point of the previously played series, respectively, and calls the onSinglePointPlayed function.

      • If an unknown key is pressed, it returns early without preventing the default behavior, allowing the browser to handle the key event as usual.
    • The speaker.cancel(); cancels any pending speech announcements.
    • The e.preventDefault(); prevents the default behavior of the keyboard event, ensuring that the keypress does not trigger other unintended actions in the browser.

    Step 5: Sonification mode

    // Start sonification mode
    document.getElementById('sonify').onclick = function () {...}

    This snippet sets up the user interface for initiating sonification mode. When the “sonify” element is clicked, it makes the control interface visible, focuses on it for user interaction, and plays a notification sound to provide feedback that the sonification mode has been activated. This helps users understand that they can now interact with the sonified data using the controls.

    Let’s break down the code:

    • The document.getElementById('sonify').onclick code attaches a click event handler to the HTML element with the id sonify. This element initiates the sonification mode when clicked.
    • Inside the click event handler function:
      • const controls = document.getElementById('controls') retrieves a reference to an HTML element with the id controls. This element is used to control and interact with the sonification.
      • controls.className = ‘visible’; updates the CSS class of the controls element to visible. As this element is initially hidden and become visible when sonification is initiated
      • setTimeout(function () { controls.focus(); }, 10) sets a timeout using setTimeout to focus on the controls element after a short delay of 10 milliseconds. Focusing on an element means that it will receive keyboard input and interactions, and in this case, it ensures that the controls element is ready to receive user input for sonification.
      • chart.sonification.playNote('vibraphone', { … }) triggers the playback of a notification sound using the playNote function of the chart’s sonification capabilities.

    I hope now you have a better understating on how to create an accessible and interactive sonification chart with keyboard navigation. Just remember to add the necessary modules, build the right HTML structure, use configuration settings, keyboard event handling, and the sonification mode.

    To learn more about sonification and audio charts using Highcharts, visit Highcharts accessibility tutorial documentation resources.