辅助功能:d3画笔/缩放可以获得焦点并通过键盘控制

Zak*_*iMa 8 javascript svg accessibility d3.js

任何提示如何使用键盘控制d3刷/变焦的提示:1.能够专注于画笔控制2.能够使用键盘更改画笔区域

开箱即用吗?

在此输入图像描述

更新:显然没有开箱即用的解决方案(希望d3会在某个时候提供它).这意味着自定义解决方案将取决于可视化/方案.发布实际的用户体验和要求,并为此特定案例提供解决方案.

为了满足可访问性要求,任务是修改下面的图表控件,以便能够使用键盘进行缩放/刷新.这包括:1)能够设置焦点; 2)能够使用左右箭头键进行控制.

在此输入图像描述

And*_*eid 4

我将使用这个作为参考。我相信这是你形象的来源。

缩放和画笔功能比较

我们对这个块中的几件事感兴趣,缩放代码和刷牙代码:

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));
Run Code Online (Sandbox Code Playgroud)

两个功能:

  • 检查函数的主体是否应该被执行
  • 设置新的 x 比例域
  • 更新面积和轴

差异很重要:

画笔函数使用 d3.zoomIdentity 更新比例,它必须执行此操作,因为它需要更新缩放函数以反映当前的缩放比例和变换。

缩放功能手动设置画笔,必须这样做,因为画笔需要更新。

在没有事件的情况下放大并刷“入”

要通过键盘控制它,使用 Brushed() 函数作为模板可能更容易。这是因为当前的缩放变换可能很难检索,而欺骗画笔的变化相对容易。

在 Brushed 函数中,d3.event.selection 中的值是一个数组,其中包含画笔所包含的值范围(范围内的值,而不是域内的值)。它是由画笔覆盖的参考/上下文比例 x2 中的最小和最大范围值的数组。这是我们唯一需要更新缩放和画笔的东西。

要放大,我们可以采用焦点 x 比例的域并找到该域的最小值和最大值。然后我们可以将焦点x尺度的域重新设置得稍微小一些,从而有效地放大。下面的代码将域转换为范围,并在将其转换回域之前缩小该范围 - 这是不需要的,但更紧密地遵循 Brushed() 函数,意味着不必处理日期。

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));
Run Code Online (Sandbox Code Playgroud)

我们还可以像这样设置缩放比例:

var identity = d3.zoomIdentity
  .scale(width/ (xMax - xMin))
Run Code Online (Sandbox Code Playgroud)

我们还想修改缩放的变换,以便放大到先前较大域的中心。以下只是示例块中使用的代码的复制,但为了便于说明,使用了更清晰的名称:

var identity = d3.zoomIdentity
  .scale(width/ (xMax - xMin))
  .translate(-xMin, 0);
Run Code Online (Sandbox Code Playgroud)

如果我们使用 Brushed 函数作为模板,我们最终可能会得到:

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
Run Code Online (Sandbox Code Playgroud)

这会将焦点区域放大到以当前域中心为中心的区域。使用上面的代码,域将缩小三分之一,但可以更改以满足您的需求。

与原始刷函数相比,唯一真正的区别是:

  • 手动计算画笔范围
  • 使用缩放功能中使用的方法更新画笔。

这就对了。

其他操作

您可以通过扩大而不是缩小域来缩小,只需在定义新端点时切换符号即可:

xMin -= currentDifference / 2 / 3  
xMax += currentDifference / 2 / 3
Run Code Online (Sandbox Code Playgroud)

向左移动看起来像:

xMin -= currentDifference / 2 / 3  
xMax -= currentDifference / 2 / 3
Run Code Online (Sandbox Code Playgroud)

自然地向右移动则相反。

添加键盘

现在您所要做的就是设置一个侦听器来侦听按键:

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

把它们放在一起

我已经组装了一个块来显示所有内容,我使用 asdw 作为关键输入:

  • a:向左平移
  • d:向右平移
  • w:放大
  • s:缩小。

最后一点:我已经进行了一项检查,以确保新域在范围内:我们不想超出数据域。

这是例子。