Pitch mapping

author(s): Øystein Moseng

by oysteinmoseng

HTML

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

<figure class="highcharts-figure">
  <button id="sonify">Play chart</button>
  <div id="container"></div>
  <p class="highcharts-description">Demo showing various types of pitch mapping.</p>
</figure>

CSS

body {
    font-family:
        -apple-system,
        BlinkMacSystemFont,
        "Segoe UI",
        Roboto,
        Helvetica,
        Arial,
        "Apple Color Emoji",
        "Segoe UI Emoji",
        "Segoe UI Symbol",
        sans-serif;
}

.highcharts-figure {
    max-width: 700px;
    margin: 0 auto;
    position: relative;
}

#sonify {
    position: absolute;
    top: 5px;
    right: 5px;
    z-index: 10;
    background-color: #fff;
    border: 1px solid #25386f;
    color: #25386f;
    font-size: 0.9rem;
    min-height: 30px;
    font-weight: 500;
    border-radius: 4px;
    padding: 0.375rem 0;
    width: 10rem;
    margin-bottom: 0.25rem;
    margin-top: 0.25rem;
    text-align: center;
    cursor: pointer;
}

#sonify:hover {
    background-color: #25386f;
    color: #fff;
}

.highcharts-description {
    margin: 0.3rem 10px;
}

JavaScript

const RawTableComponent = function (chart) { this.initBase(chart); };
      RawTableComponent.prototype = new Highcharts.AccessibilityComponent();
      Highcharts.extend(RawTableComponent.prototype, {
        onChartUpdate() {
          const btn = document.getElementById('show-raw-table');
          if (btn) {
            btn.setAttribute('tabindex', '-1');
            Highcharts.A11yChartUtilities.unhideChartElementFromAT(this.chart, btn);
          }
        },
        getKeyboardNavigation() {
          const keys = this.keyCodes, btn = document.getElementById('show-raw-table');
          return new Highcharts.KeyboardNavigationHandler(this.chart, {
            keyCodeMap: [
              [[keys.left, keys.up], () => this.response.prev],
              [[keys.right, keys.down, keys.tab], () => this.response.next],
              [[keys.enter, keys.space], () => { btn?.click(); return this.response.success; }]
            ],
            init() { btn?.focus(); }
          });
        }
      });

      const chart = Highcharts.chart('quarter-chart', {
        accessibility: { keyboardNavigation: { enabled: true } },
        series: [{ name: 'Q1', color: '#7cb5ec', data: jsonData }]
      });

      chart.update({
        accessibility: {
          customComponents: { rawTable: new RawTableComponent(chart) },
          keyboardNavigation: { order: ['series', 'rawTable', 'chartMenu'] }
        }
      });