d3-brush
刷选是指使用指向手势(例如单击并拖动鼠标)交互式地指定一个或二维选定区域。刷选通常用于选择离散元素,例如散点图中的点或桌面上的文件。它也可以用于放大感兴趣的区域,或选择连续区域以进行 跨过滤器数据 或实时直方图
d3-brush 模块使用 SVG 为鼠标和触摸事件实现刷选。单击并拖动刷选区域以平移选定区域。单击并拖动其中一个选定句柄以移动选定区域的相应边(或边)。单击并拖动不可见的覆盖层以定义新的刷选区域,或者在可刷选区域内单击并按住 META(⌘)键。在移动刷选时按住 ALT(⌥)键会导致其围绕其中心重新定位,而按住 SPACE 键会锁定当前刷选大小,只允许平移。
刷选还支持程序化控制。例如,您可以监听 结束 事件,然后使用 brush.move 启动过渡以将刷选区域捕捉到语义边界
或者您可以让刷选区域在您单击当前选定区域之外时重新居中
brush()
brushX()
brushY()
源代码 · 创建一个沿 y 维度的新一维刷选。
brush(group)
示例 · 源代码 · 将刷选应用于指定的 group,它必须是 SVG G 元素 的 选择。此函数通常不会直接调用,而是通过 selection.call 调用。例如,要渲染一个刷选
svg.append("g")
.attr("class", "brush")
.call(d3.brush().on("brush", brushed));
在内部,刷选使用 selection.on 来绑定必要的拖动事件监听器。监听器使用名称 .brush
,因此您可以随后取消绑定刷选事件监听器,如下所示
group.on(".brush", null);
刷选还会创建显示刷选区域和接收交互输入事件所需的 SVG 元素。您可以根据需要添加、删除或修改这些元素以更改刷选外观;您也可以应用样式表以修改刷选外观。二维刷选的结构如下所示
<g class="brush" fill="none" pointer-events="all" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);">
<rect class="overlay" pointer-events="all" cursor="crosshair" x="0" y="0" width="960" height="500"></rect>
<rect class="selection" cursor="move" fill="#777" fill-opacity="0.3" stroke="#fff" shape-rendering="crispEdges" x="112" y="194" width="182" height="83"></rect>
<rect class="handle handle--n" cursor="ns-resize" x="107" y="189" width="192" height="10"></rect>
<rect class="handle handle--e" cursor="ew-resize" x="289" y="189" width="10" height="93"></rect>
<rect class="handle handle--s" cursor="ns-resize" x="107" y="272" width="192" height="10"></rect>
<rect class="handle handle--w" cursor="ew-resize" x="107" y="189" width="10" height="93"></rect>
<rect class="handle handle--nw" cursor="nwse-resize" x="107" y="189" width="10" height="10"></rect>
<rect class="handle handle--ne" cursor="nesw-resize" x="289" y="189" width="10" height="10"></rect>
<rect class="handle handle--se" cursor="nwse-resize" x="289" y="272" width="10" height="10"></rect>
<rect class="handle handle--sw" cursor="nesw-resize" x="107" y="272" width="10" height="10"></rect>
</g>
覆盖矩形覆盖由 brush.extent 定义的可刷选区域。选择矩形覆盖由当前 刷选区域 定义的区域。句柄矩形覆盖刷选区域的边缘和角,允许交互式地修改刷选区域中的相应值。要以编程方式修改刷选区域,请使用 brush.move.
brush.move(group, selection, event)
示例 · 源代码 · 在指定的 group 上设置刷选的活动 selection,它必须是 SVG G 元素 的 选择 或 过渡。selection 必须定义为一个数字数组,或为 null 以清除刷选区域。对于 二维刷选,它必须定义为 [[x0, y0], [x1, y1]],其中 x0 是最小 x 值,y0 是最小 y 值,x1 是最大 x 值,而 y1 是最大 y 值。对于 x 刷选,它必须定义为 [x0, x1];对于 y 刷选,它必须定义为 [y0, y1]。选定区域也可以指定为一个函数,该函数返回这样的数组;如果是一个函数,它将为每个选定元素调用,并传递当前数据 d
和索引 i
,其中 this
上下文为当前 DOM 元素。返回的数组定义该元素的刷选区域。
brush.clear(group, event)
示例 · 源代码 · brush.move 的别名,带有 null 选定区域。
brush.extent(extent)
示例 · 源代码 · 如果指定了 extent,则将可刷选区域设置为指定点的数组 [[x0, y0], [x1, y1]],其中 [x0, y0] 是左上角,而 [x1, y1] 是右下角,并返回此刷选。extent 也可以指定为一个函数,该函数返回这样的数组;如果是一个函数,它将为每个选定元素调用,并传递当前数据 d
和索引 i
,其中 this
上下文为当前 DOM 元素。如果未指定 extent,则返回当前区域访问器,该访问器默认为
function defaultExtent() {
var svg = this.ownerSVGElement || this;
if (svg.hasAttribute("viewBox")) {
svg = svg.viewBox.baseVal;
return [[svg.x, svg.y], [svg.x + svg.width, svg.y + svg.height]];
}
return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
}
此默认实现要求拥有者 SVG 元素具有定义的 viewBox,或 width 和 height 属性。或者,考虑使用 element.getBoundingClientRect。(在 Firefox 中,element.clientWidth 和 element.clientHeight 对于 SVG 元素为零!)
刷选区域决定了不可见覆盖层的大小,也限制了刷选区域;刷选区域不能超出刷选区域。
brush.filter(filter)
示例 · 源代码 · 如果指定了 filter,则将过滤器设置为指定的函数并返回刷选。如果未指定 filter,则返回当前过滤器,该过滤器默认为
function filter(event) {
return !event.ctrlKey && !event.button;
}
如果过滤器返回假值,则会忽略启动事件,并且不会启动任何刷选手势。因此,过滤器确定哪些输入事件会被忽略。默认过滤器会忽略次要按钮上的 mousedown 事件,因为这些按钮通常用于其他目的,例如上下文菜单。
brush.touchable(touchable)
源代码 · 如果指定了 touchable,则将触摸支持检测器设置为指定的函数并返回刷选。如果未指定 touchable,则返回当前触摸支持检测器,该检测器默认为
function touchable() {
return navigator.maxTouchPoints || ("ontouchstart" in this);
}
只有当检测器在刷选 应用 时对于相应元素返回真值时,才会注册触摸事件监听器。默认检测器适用于大多数能够进行触摸输入的浏览器,但并非所有浏览器;例如,Chrome 的移动设备模拟器无法检测到。
brush.keyModifiers(modifiers)
源代码 · 如果指定了 modifiers,则设置刷选在刷选期间是否监听按键事件并返回刷选。如果未指定 modifiers,则返回当前行为,该行为默认为 true。
brush.handleSize(size)
源代码 · 如果指定了 size,则将画笔手柄的大小设置为指定数字并返回画笔。如果未指定 size,则返回当前手柄大小,默认值为 6。此方法必须在 将画笔应用于选择 之前调用;更改手柄大小不会影响之前呈现的画笔。
brush.on(typenames, listener)
源代码 · 如果指定了 listener,则为指定的 typenames 设置事件 listener 并返回画笔。如果已为相同类型和名称注册了事件监听器,则在添加新的监听器之前会移除现有的监听器。如果 listener 为 null,则移除指定的 typenames 的当前事件监听器(如果有)。如果未指定 listener,则返回与指定的 typenames 匹配的第一个当前分配的监听器(如果有)。当分派指定事件时,每个 listener 将使用与 selection.on 监听器相同的上下文和参数调用:当前事件 event
和数据 d
,其中 this
上下文为当前 DOM 元素。
typenames 是一个字符串,包含一个或多个用空格分隔的 typename。每个 typename 是一个 type,后面可以 optionally 跟着一个点 (.
) 和一个 name,例如 brush.foo
和 brush.bar
;名称允许为相同 type 注册多个监听器。type 必须是以下之一
start
- 在画笔手势开始时,例如在鼠标按下时。brush
- 当画笔移动时,例如在鼠标移动时。end
- 在画笔手势结束时,例如在鼠标松开时。
有关更多信息,请参阅 dispatch.on 和 画笔事件。
brushSelection(node)
示例 · 源代码 · 返回指定 node 的当前画笔选择。在内部,元素的画笔状态存储为 element.__brush;但是,您应该使用此方法而不是直接访问它。如果给定的 node 没有选择,则返回 null。否则,selection 被定义为一个数字数组。对于 二维画笔,它是 [[x0, y0], [x1, y1]],其中 x0 是最小 x 值,y0 是最小 y 值,x1 是最大 x 值,y1 是最大 y 值。对于 x 画笔,它是 [x0, x1];对于 y 画笔,它是 [y0, y1]。
画笔事件
当调用 画笔事件监听器 时,它会收到当前的画笔事件。event 对象公开了一些字段