1.能够专注于画笔控制
2.能够使用键盘更改画笔区域
是否支持开箱即用?
更新:显然没有开箱即用的解决方案(希望d3会在某个时候提供它).这意味着自定义解决方案将取决于可视化/方案.发布实际的用户体验和要求,并为此特定案例提供解决方案.
为了满足可访问性要求,任务是修改下面的图表控件,以便能够使用键盘进行缩放/刷新.这包括:1)能够设置焦点; 2)能够使用左右箭头键进行控制.
解决方法
缩放和画笔功能比较
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比例域
>更新区域和轴
差异很重要:
刷子功能使用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));
我们也可以这样设置缩放比例:
var identity = d3.zoomIdentity .scale(width/ (xMax - xMin))
我们还想修改缩放的变换,以便我们放大到前一个更大域的中心.以下只是示例块中使用的代码的再现,但为了说明,名称更清晰:
var identity = d3.zoomIdentity .scale(width/ (xMax - xMin)) .translate(-xMin,0);
如果我们使用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,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:缩小.
最后一点:我已经包含了一项检查,以确保新域位于边界内:我们不想缩放超出数据域的范围.
Here’s的例子.