将画笔限制为离散范围

时间:2013-08-05 18:50:14

标签: javascript user-interface user-controls d3.js brush

我想让用户使用brush选择一系列值。但是,在我的应用程序中只有离散值才有意义,因此我想将画笔限制为这些离散值(例如整数)。

这样做的一种方法是使用Ordinal Brushing中描述的方法。在该示例中,画笔本身可以采用连续值,然后将其映射到序数标度的离散值。

我想在用户刷牙或拖动画笔时获取一个用于捕捉离散值的画笔。我想出了一些基本上可行的方法:舍入target.extent然后重新选择舍入范围(Fiddle):

function brush() {
    var s = d3.event.target.extent();
    if (d3.event.mode === "move") {
        var extentlength = Math.round(s[1] - s[0])
        d3.event.target.extent([Math.round(s[0] + 0.5) - 0.5,
        Math.round(s[0] + 0.5) - 0.5 + extentlength])
    } else {
        d3.event.target.extent([Math.round(s[0] + 0.5) - 0.5,
        Math.round(s[1] + 0.5) - 0.5])
    }
    d3.event.target(d3.select(this))
}

然而,这感觉有点笨拙,并且它导致不良行为,当用户拖动画笔时,光标可以悬停在画笔的边缘上,将光标符号从“拖动”转向“调整大小“ - 箭头。

是否有一种更优雅,更健壮的方式来获得只允许选择离散范围的画笔?

1 个答案:

答案 0 :(得分:3)

这可能会过多地挖掘D3用于渲染画笔的svg节点的内部,但一种解决方案是选择这些节点并更改其光标样式。在您的示例中,生成的画笔节点如下所示(我修剪了一些属性):

<g style="pointer-events: all;">
  <rect class="background" style="visibility: hidden; cursor: crosshair;"></rect>
  <rect class="extent" style="cursor: move;"></rect>
  <g class="resize e" style="cursor: ew-resize;">
    <rect style="visibility: hidden;"></rect>
  </g>
  <g class="resize w" style="cursor: ew-resize;">
    <rect style="visibility: hidden;"></rect>
  </g>
</g>

因此,例如,您可以在刷子事件期间完全禁用调整大小游标:

var brush = d3.svg.brush().x(x).extent([0.5, 1.5])
    .on("brushstart", brushstart)
    .on("brush", brush)
    .on("brushend", brushend);

function brushstart() {
  // disable the resizing cursor
  var resizers = d3.select(this).selectAll('g.resize')
    .style("cursor", "auto");
}

function brushend() {
  // re-enable the resizing cursor
  var resizers = d3.select(this).selectAll('g.resize')
    .style("cursor", "ew-resize");
}

正如我所说的那样,这会让你在未来的版本中更改刷子的svg节点结构的危险,但它在概念和计算上相当简单。刷子事件中的this表示刷子本身的外部<g>节点,因此我们只需在该级别下应用选择器来查找调整大小节点。

更进一步,您可以在brush函数本身中添加额外的逻辑来更改游标,但是这会在鼠标移动时进行评估,因此会更加昂贵。