2

我想让用户使用brush. 但是,只有离散值在我的应用程序中才有意义,所以我想将画笔限制为这些离散值(比如整数)。

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

我想要一个在用户刷或拖动画笔时捕捉到离散值的画笔。我想出了一些基本可行的方法:四舍五入target.extent然后重新选择四舍五入的范围(小提琴):

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))
}

但是,这感觉有点笨拙,并且会导致不良行为,即当用户拖动画笔时,光标可以悬停在画笔边缘,将光标符号从“拖动”手变成“调整大小”-箭。

是否有一种更优雅、更强大的方式来获取只允许选择离散范围的画笔?

4

1 回答 1

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");
}

正如我所说,这会让您面临 D3 在未来版本中更改画笔的 svg 节点结构的危险,但它在概念上和计算上相当简单。内部this画笔事件代表画笔本身的外部<g>节点,因此我们只需在该级别下方应用选择器即可找到调整大小的节点。

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

于 2013-08-09T22:42:25.590 回答