Highcharts accessibility module with {highcharter}: Part 3

R data visualization accessibility highcharter Highcharts

Re-creating Highcharts’ accessible pie chart using the {highcharter} R package.

Mara Averick https://twitter.com/dataandme
2021-11-13

In the first two parts of this series we introduced the Highcharts accessibility module, the {highcharter} R package, and created some working examples with accessibility features turned on.

Here, we’ll follow in the vein as part 2 by re-creating one of the accessible chart demos from Highcharts.

Accessible pie chart

Highcharts’ accessible pie chart isn’t what I’d call “easy on the eyes.” Heck, they even added an option to turn the pattern fills off (a feat that I do not accomplish below).

library(highcharter)
highchart() %>%
  # add dependencies
  hc_add_dependency(name = "modules/exporting.js") %>%
  hc_add_dependency(name = "modules/export-data.js") %>%
  hc_add_dependency(name = "modules/accessibility.js") %>%
  hc_add_dependency(name = "modules/pattern-fill.js") %>%
  hc_tooltip(
    valueSuffix = "%",
    borderColor = "#8ae"
  ) %>%
  hc_title(text = "Primary desktop/laptop screen readers") %>%
  hc_subtitle(text = "Source: WebAIM.") %>%
  hc_caption(text = "Pie chart demonstrating some accessibility features of Highcharts. The chart shows which screen reader is used as the primary screen reader by the respondents, with NVDA currently being the most popular one. The JAWS screen reader is following closely behind.") %>%
  hc_exporting(
    enabled = TRUE,
    accessibility = list(
      enabled = TRUE
    )
  ) %>%
  hc_add_series(
    type = "pie",
    name = "Screen reader usage",
    data = list(
      list(
        name = "NVDA",
        y = 40.6,
        color = list(
          pattern = list(
            path = "M 0 0 L 5 5 M 4.5 -0.5 L 5.5 0.5 M -0.5 4.5 L 0.5 5.5",
            color =  "#0b7383",
            width = 5,
            height = 5,
            patternTransform =  "scale(1.4 1.4)"
          )
        )
      ),
      list(
        name = "JAWS",
        y = 40.1,
        color = list(
          pattern = list(
            path = "M 0 5 L 5 0 M -0.5 0.5 L 0.5 -0.5 M 4.5 5.5 L 5.5 4.5",
            color = "#4372da",
            width = 5,
            height = 5,
            patternTransform = "scale(1.4 1.4)"
          )
        )
      ),
      list(
        name = "VoiceOver",
        y = 12.9,
        color = list(
          pattern = list(
            path = "M 2 0 L 2 5 M 4 0 L 4 5",
            color = "#6B26F0",
            width = 5,
            height = 5,
            patternTransform = "scale(1.4 1.4)"
          )
        )
      ),
      list(
        name = "ZoomText",
        y = 2,
        color = list(
          pattern = list(
            path = "M 0 2 L 5 2 M 0 4 L 5 4",
            color = "#222",
            width = 5,
            height = 5,
            patternTransform = "scale(1.4 1.4)"
          )
        )
      ),
      list(
        name = "Other",
        y = 4.4,
        color = list(
          pattern = list(
            path = "M 0 1.5 L 2.5 1.5 L 2.5 0 M 2.5 5 L 2.5 3.5 L 5 3.5",
            color = "#D42D1A",
            width = 5,
            height = 5,
            patternTransform = "scale(1.4 1.4)"
          )
        )
      )
    )
  ) %>%
  hc_plotOptions(
    series = list(
      dataLabels = list(
        enabled = TRUE,
        connectorColor = "#777",
        format = "<b>{point.name}</b>: {point.percentage:.1f} %"
      ),
      cursor = "pointer",
      borderWidth = 3
    ),
    accessibility = list(
      enabled = TRUE,
      keyboardNavigation = list(enabled = TRUE)
    )
  )

As with the first version of the accessible line chart in part 2 of this series, the code here doesn’t look terribly R-like (in fact, we’re not using a data-frame object at all). The reason is the same, too: in order to get the dual encoding (in this case, colour + pattern), each item was defined individually.

The code above is very much reflects the fact that I reverse engineered this chart from the original version, which combined the indexed pattern definitions from the Highcharts pattern fill module with colours (see un-run JavaScript code below).

var clrs = Highcharts.getOptions().colors;
var pieColors = [clrs[2], clrs[0], clrs[3], clrs[1], clrs[4]];
// Get a default pattern, but using the pieColors above.
// The i-argument refers to which default pattern to use
function getPattern(i) {
    return {
        pattern: Highcharts.merge(Highcharts.patterns[i], {
            color: pieColors[i]
        })
    };
}
// Get 5 patterns
var patterns = [0, 1, 2, 3, 4].map(getPattern);

I imagine there’s a way to reference the patternIndex from the R code, but I wasn’t able to figure it out. I actually ran the JavaScript in my console to get the color/pattern definitions (e.g. Highcharts.patterns[0]) used for each item in the series.

Takeaways?

I’d say the main lesson learned for this one was that the vignette written by Tom Bishop in the {highcharter} docs, JavaScript API Basics, is helpful and accurate:

loosely understanding…how functions and their arguments map to build JSON objects that define JavaScript Highcharts should supercharge your use of the R package.

Next time, we’ll take a closer look at my personal favorite feature from the accessibility module: the information for screen readers generated.

Reuse

Text and figures are licensed under Creative Commons Attribution CC BY 4.0. The figures that have been reused from other sources don't fall under this license and can be recognized by a note in their caption: "Figure from ...".

Citation

For attribution, please cite this work as

Averick (2021, Nov. 13). dataand.me: Highcharts accessibility module with {highcharter}: Part 3. Retrieved from https://dataand.me/posts/2021-11-13-highcharts-accessibility-module-with-highcharter-part-3/

BibTeX citation

@misc{averick2021highcharts,
  author = {Averick, Mara},
  title = {dataand.me: Highcharts accessibility module with {highcharter}: Part 3},
  url = {https://dataand.me/posts/2021-11-13-highcharts-accessibility-module-with-highcharter-part-3/},
  year = {2021}
}