plotly.js icon indicating copy to clipboard operation
plotly.js copied to clipboard

Use keyboard to navigate plotly charts

Open johnpauls opened this issue 9 years ago • 21 comments

I like plotly and its integration with R's ggplot, but I find that I cannot use the keyboard to interact with plotly charts or the button bar at the top of the charts. This is a concern when making websites more accessible to people with disabilities. Could this be added?

johnpauls avatar May 24 '16 14:05 johnpauls

thanks for reporting @johnpauls ! could you elaborate more on what you would expect the keyboard interactions to be?

chriddyp avatar May 24 '16 16:05 chriddyp

@chriddyp In the US there is a law, referred to as section 508, that governs web compliance for the federal government (at least) and is used as a benchmark by others. Basically one part says that anything you can do with the mouse you should be able to do with just the keyboard (note - not a lawyer).

So I guess at least you would want to be able to activate/interact with all of the controls on the button bar and click the colors on the legends (where appropriate) by tabbing through them or something similar. It would also be good if you could use the keyboard move the cursor to hover over the various charts and see the information that is displayed (coordinates or values or whatever).

Thanks

johnpauls avatar May 24 '16 16:05 johnpauls

It is possible we could add these in the future, but I'm not sure whether we should beyond very basic interactions. Plotly.js' main focus is on plotting the data and exposing an interface to view it - in my opinion, specific key events should be managed by the consumers of plots (i.e. webpages they are embedded in).

Simple pan/zoom controls would be useful (z for zoom in, shift+z for zoom out, arrow keys to navigate) and not too too difficult to implement. Legends would be a bit more difficult to make keyboard-friendly because visual aids would need to be added (they are in SVG, not HTML), and any sort of cursor on the plot would be a fairly significant addition.

For now, if you are embedding plots in a webpage and need a11y, I'd suggest using the javascript API to bind whatever actions are required to keys - it's a difficult thing to generalize beyond zooming and scrolling, but those are both fairly easily implemented by changing axis ranges and calling Plotly.relayout.

var graph = document.getElementById('graph');

Plotly.plot(graph, [{
  x: [1, 2, 3],
  y: [2, 3, 4]
}], {});

// Basic example to zoom on z
window.addEventListener('keyup', function(e){
  var key = e.keyCode ? e.keyCode : e.which;

  // 'z' key is 90
  if(key === 90) {
    var oldRange = graph._fullLayout.xaxis.range;
    var oldMin = oldRange[0];
    var oldMax = oldRange[1];

    var scaling = e.shiftKey ? -0.1 : 0.1;

    var newRange = [
      oldRange[0] + (oldMax - oldMin) * scaling,
      oldRange[1] - (oldMax - oldMin) * scaling
    ];
    Plotly.relayout(graph, 'xaxis.range', newRange);
  }
});

And a live jsbin

mdtusz avatar May 24 '16 17:05 mdtusz

Thanks for this suggestion. For what its worth, my hope it to use plotly to create graphics in R and then server them on the web using RStudio's shiny /shiny server . I would like to avoid adding the extra javascript, but it is good to know that it can be done.

johnpauls avatar May 27 '16 12:05 johnpauls

I'd like this feature, too.

Some pretty basic shortcuts would already help tremendously especially when you have to use a laptop trackpad. I previously used matplotlibs interactive window and immediatly tried to use the shortcuts in plotly, too. The matplotlib toolbar shortcuts are listed here:

https://matplotlib.org/users/navigation_toolbar.html

legg681 avatar Apr 20 '17 07:04 legg681

Typical keyboard interaction for a custom component is to use the TAB key (and SHIFT+TAB) to navigate into and out of the component, and to use arrow keys (UP, DOWN, LEFT, RIGHT) to navigate within the component. Please try using your keyboard in any of these Oracle JET charts/visualizations. Notice also that they also use aria-label where invisible labels are needed for screen reader users, and sometimes they use role="img" or role="separator" and other aria to help clarify what various things represent.

carmacleod avatar Sep 05 '18 02:09 carmacleod

From #3989

Is it possible to have shortcuts for interactions with the graph?

E.g. I would like to have

  • panning with the arrow keys left, right, up, down
  • zooming with + and -
  • horizontal zooming with ctrl+left and ctrl+right
  • vertical zooming with ctrl+up and ctrl+down
  • unzoom both u, horizontal unzoom alt+x, vertical unzoom alt+y
  • previous zoom p
  • toggle grid g
  • snapshot (copy as png to clibboard) ctrl+c

(partly taken from gnuplot).

etpinard avatar Jun 27 '19 13:06 etpinard

Thanks for pointing me here.

How I can fed this javascript snippet outlined above by @mdtusz from python to the html document?

mzechmeister avatar Jun 27 '19 16:06 mzechmeister

I created a some more key bindings, that be tested here https://jsfiddle.net/jrL34keb/1/.

I found no way pass the additional javascript to python via the plot function. But there are functions https://github.com/plotly/plotly.py/blob/dc1111170d017911699d0f940850c45bd4f3e98e/plotly/offline/offline.py#L371 which have a post_script argument. As a bad hack, I made a decorator to a function, which generates itself post_javascript code, in order to append the binding script.

When putting the following code at the top of the python script, it appends automatically key bindings in every offline.plot call.

import plotly

import plotly.plotly as py
import plotly.graph_objs as go
bind_script = '''
var graph = document.getElementsByClassName("plotly-graph-div js-plotly-plot")[0];
var update;

function pan(axis, dx, mode=1) {
    axis += 'axis';
    var [min, max] = graph._fullLayout[axis].range;
    dx *= max - min;
    update[axis+'.range'] = [min+dx, max+mode*dx];
}

function panX(dx) {pan('x', dx)}
function panY(dy) {pan('y', dy)}
function zoomX(dx) {pan('x', dx, -1)}
function zoomY(dy) {pan('y', dy, -1)}

document.addEventListener("keydown", function(e){
    var key = e.key;
    if (e.ctrlKey) key = 'Ctrl+' + key;
    console.log(e, key);
    var fac = 0.1;   // pan and zoom factor
    update = {};
    var extremes = graph._fullData[0]._extremes;  // only first data set
    switch (key) {
        case 'Ctrl+ArrowRight': zoomX(fac); break;
        case 'Ctrl+ArrowLeft': zoomX(-fac); break;
        case 'Ctrl+ArrowUp': zoomY(fac); break;
        case 'Ctrl+ArrowDown': zoomY(-fac); break;
        case '+': zoomX(fac); zoomY(fac); break;
        case '-': zoomX(-fac); zoomY(-fac); break;
        case 'X': case 'U':
             update['xaxis.range'] = [extremes.x.min[0].val, extremes.x.max[0].val];
        case 'Y': case 'U':
             update['yaxis.range'] = [extremes.y.min[0].val, extremes.y.max[0].val]; break;
        case 'x': case 'u':
             update['xaxis.autorange'] = true;
        case 'y': case 'u':
             update['yaxis.autorange'] = true; break;
        case '0': update['yaxis.range[0]'] = 0; break;
        case 'ArrowRight': panX(fac); break;
        case 'ArrowLeft': panX(-fac); break;
        case 'ArrowUp': panY(fac); break;
        case 'ArrowDown': panY(-fac); break;
        case 'Home': panX(-1.); break;
        case 'End': panX(1.); break;
        case 'PageUp': panY(1.); break;
        case 'PageDown': panY(-1.); break;
        default: return;
    }
    Plotly.relayout(graph, update);
});
'''


def script_decorator(func):
    # append binding script
    def function_wrapper(*x):
        return (func(*x) or '') + bind_script
    return function_wrapper

plotly.offline.offline.build_save_image_post_script = script_decorator(plotly.offline.offline.build_save_image_post_script)

mzechmeister avatar Jun 28 '19 11:06 mzechmeister

Is there any update on being able to navigate through plotly chart using keyboard?

mizeljko avatar Jan 14 '20 21:01 mizeljko

I wonder whether there are any updates? Thanks!

fzyzcjy avatar Mar 30 '20 08:03 fzyzcjy

Just Zoom In, Zoom Out and Pan shortcuts alone should be great. Thank you.

GitHunter0 avatar Jun 17 '20 18:06 GitHunter0

This issue has been tagged with NEEDS SPON$OR

A community PR for this feature would certainly be welcome, but our experience is deeper features like this are difficult to complete without the Plotly maintainers leading the effort.

What Sponsorship includes:

  • Completion of this feature to the Sponsor's satisfaction, in a manner coherent with the rest of the Plotly.js library and API
  • Tests for this feature
  • Long-term support (continued support of this feature in the latest version of Plotly.js)
  • Documentation at plotly.com/javascript
  • Possibility of integrating this feature with Plotly Graphing Libraries (Python, R, F#, Julia, MATLAB, etc)
  • Possibility of integrating this feature with Dash
  • Feature announcement on community.plotly.com with shout out to Sponsor (or can remain anonymous)
  • Gratification of advancing the world's most downloaded, interactive scientific graphing libraries (>50M downloads across supported languages)

Please include the link to this issue when contacting us to discuss.

jackparmer avatar Sep 10 '20 19:09 jackparmer

A couple of links that may prove of interest: WebAIM describe how keyboard accessibility is one of the most important aspects of web accessibility.

Also an interesting talk from Google about how designing for accessibility improves product quality and benefits everyone.

dotcode avatar Jun 22 '21 16:06 dotcode

Is there any new version released for plotly.js Keyboard accessibility.

trmdev avatar Feb 02 '22 19:02 trmdev

This issue has been tagged with NEEDS SPON$OR ...

Given that I personally don't have $20k to throw at this but would happily donate 0.1% of that to help it get done, is there an existing process setup that would facilitate this getting crowd-sponsored? Can we designate this issue on GitHub Sponsorships? (If Dash customers have this same problem maybe they could upvote it somehow?)

jacobq avatar Apr 25 '22 21:04 jacobq

BTW, the javascript part of my snippet I posted above is now maintained as a standalone file: https://github.com/mzechmeister/csvplotter/blob/main/zoom_pan.js The project readme explains the available shortcuts.

mzechmeister avatar Apr 11 '23 13:04 mzechmeister

I would like to give my idea about using key arrow left, right for the slider to redraw frames. moving slider by frames is not easily control especially when you have a very long range, so keyboard would be more convinient when you want to go through frame by frame easily

LeoDiep avatar May 24 '24 03:05 LeoDiep

+1 for adding keyboard shortcuts for exploring the graph. This will be very helpful. Will keep an eye here!

deven298 avatar Jun 28 '24 18:06 deven298