Accessibility: d3 brush / zoom can get focus and control the keyboard

Any tips on how to control the brush / zoom d3 using the keyboard: 1. Ability to concentrate on controlling the brush 2. Ability to change the area of ​​the brush using the keyboard

Is it supported out of the box?

enter image description here

Refresh . There seems to be no ready-made solution (hopefully d3 will provide it at some point). This means that the custom solution will depend on the visualization / script. Publishing the actual UX and requirements will provide a solution for this particular case.

, , , / . : 1) ; 2) .

enter image description here

+6
2

bl.ock . , .

, :

function brushed() {
  if (d3.event.sourceEvent && d3.event.sourceEvent.type === "zoom") return; // ignore brush-by-zoom
  var s = d3.event.selection || x2.range();
  x.domain(s.map(x2.invert, x2));
  focus.select(".area").attr("d", area);
  focus.select(".axis--x").call(xAxis);
  svg.select(".zoom").call(zoom.transform, d3.zoomIdentity
      .scale(width / (s[1] - s[0]))
      .translate(-s[0], 0));
}

function zoomed() {
  if (d3.event.sourceEvent && d3.event.sourceEvent.type === "brush") return; // ignore zoom-by-brush
  var t = d3.event.transform;
  x.domain(t.rescaleX(x2).domain());
  focus.select(".area").attr("d", area);
  focus.select(".axis--x").call(xAxis);
  context.select(".brush").call(brush.move, x.range().map(t.invertX, t));

:

  • , .
  • x scale

:

, d3.zoomIdentity, , , .

, , .

""

, , brushed() . , , .

d3.event.selection , , ( , ). /, x2, . , , .

, x . x, , . - , () .

var xMin = x2(x.domain()[0]);
var xMax = x2(x.domain()[1]);

var currentDifference = Math.abs(xMin-xMax);

xMin += currentDifference / 2 / 3   // increase the minimum value of the domain
xMax -= currentDifference / 2 / 3   // decrease the maximum value of the domain
x.domain([xMin,xMax].map(x2.invert, x2));

:

var identity = d3.zoomIdentity
  .scale(width/ (xMax - xMin))

, . - , , :

var identity = d3.zoomIdentity
  .scale(width/ (xMax - xMin))
  .translate(-xMin, 0);

, :

var xMin = x2(x.domain()[0]); // minimum value in x range currently
var xMax = x2(x.domain()[1]); // maximum value in x range currently

var currentDifference = Math.abs(xMax-xMin); // center point of range

xMin += currentDifference / 2 / 3  // reduce the distance between center point and end points
xMax -= currentDifference / 2 / 3

x.domain([xMin,xMax].map(x2.invert, x2));  // convert the range to a domain
focus.select(".area").attr("d", area); // redraw the chart
focus.select(".axis--x").call(xAxis);  // redraw the axis

var identity = d3.zoomIdentity
  .scale(width/ (xMax - xMin))
          .translate(-xMin, 0);          // update the zoom factor

context.select(".brush").call(brush.move, x.range().map(identity.invertX, identity)); // update the brush
svg.select(".zoom").call(zoom.transform, identity); // apply the zoom factor

, . , .

:

  • , .

.

, , :

xMin -= currentDifference / 2 / 3  
xMax += currentDifference / 2 / 3

:

xMin -= currentDifference / 2 / 3  
xMax -= currentDifference / 2 / 3

.

:

d3.select("body")
  .on("keypress", function() {
    if (d3.event.key == "a") {
      // one of zoom in/out/pan
    }
    else if (d3.event.key == "b" {
      //...
    }
});

, , asdw :

  • a:
  • d:
  • w:
  • s: .

: , , : .

.

+2

SVG 2.0 , SVG 1.0 , <a xlink:href="#">, / . , , / .

private createResizeTick(resizeClass: string, id: string, brushTickClass: string, tickIndex: number, bottom: number) {
    let self = this;
    // +++++++++++++++++++ NEW CODE +++++++++++++++++++
    let aElement = this._xBrushElement.selectAll(resizeClass)
        .append('a')
        .attr('id', id)
        .attr('xlink:href', '#')
        .on('keydown', () => { 
            if ((<KeyboardEvent>d3.event).keyCode !== 37 && (<KeyboardEvent>d3.event).keyCode !== 39) {
                return;
            }
            // A function which adjusts brush domain (specific to data model)
            self.brushKeyMove((<KeyboardEvent>d3.event).keyCode, tickIndex);
        })
        .on('keyup', () => {
            if ((<KeyboardEvent>d3.event).keyCode !== 37 && (<KeyboardEvent>d3.event).keyCode !== 39) {
                return;
            }
            self.brushOnEnd(); // A function which already processes native onBrushEnd event
            document.getElementById(id).focus();
        });
    // --------------- END OF NEW CODE ---------------
    aElement.append('text')
        .attr('class', 'brushtick ' + brushTickClass)
        .attr('transform', 'translate(0,' + bottom + ')')
        .attr('x', 0)
        .attr('y', 6)
        .attr('dy', '0.35em');
}

:

enter image description here

0

All Articles