d3-brush
画笔是一种交互式规范,使用指向手势(例如单击并拖动鼠标)来选择一维或二维区域。画笔通常用于选择离散元素,例如散点图中的点或桌面上的文件。它还可用于放大感兴趣的区域,或为 交叉过滤数据 或实时直方图选择连续区域:
¥Brushing is the interactive specification a one- or two-dimensional selected region using a pointing gesture, such as by clicking and dragging the mouse. Brushing is often used to select discrete elements, such as dots in a scatterplot or files on a desktop. It can also be used to zoom-in to a region of interest, or to select continuous regions for cross-filtering data or live histograms:
d3-brush 模块使用 SVG 实现鼠标和触摸事件的刷涂。点击并拖动画笔选择对象可平移选择对象。点击并拖动其中一个选择句柄可移动选择对象的相应边(或多条边)。点击并拖动不可见的叠加层可定义新的画笔选择对象,或者按住 META (⌘) 键并点击可刷区域内的任意位置。移动画笔时按住 ALT (⌥) 键可使其围绕中心重新定位,按住 SPACE 键可锁定当前画笔大小,仅允许平移。
¥The d3-brush module implements brushing for mouse and touch events using SVG. Click and drag on the brush selection to translate the selection. Click and drag on one of the selection handles to move the corresponding edge (or edges) of the selection. Click and drag on the invisible overlay to define a new brush selection, or click anywhere within the brushable region while holding down the META (⌘) key. Holding down the ALT (⌥) key while moving the brush causes it to reposition around its center, while holding down SPACE locks the current brush size, allowing only translation.
画笔也支持编程控制。例如,你可以监听 结束事件,然后使用 brush.move 启动过渡,将画笔选择捕捉到语义边界:
¥Brushes also support programmatic control. For example, you can listen to end events, and then initiate a transition with brush.move to snap the brush selection to semantic boundaries:
或者,当你点击当前选择范围之外的区域时,可以让画笔重新居中:
¥Or you can have the brush recenter when you click outside the current selection:
brush()
¥Examples · Source · Creates a new two-dimensional brush.
brushX()
¥Examples · Source · Creates a new one-dimensional brush along the x-dimension.
brushY()
源代码 · 沿 y 轴创建一个新的一维画笔。
¥Source · Creates a new one-dimensional brush along the y-dimension.
brush(group) {#_brush}
示例 · 源代码 · 将画笔应用于指定的组,该组必须是 SVG G 元素 中的一个 selection。此函数通常不直接调用,而是通过 selection.call 调用。例如,渲染画笔:
¥Examples · Source · Applies the brush to the specified group, which must be a selection of SVG G elements. This function is typically not invoked directly, and is instead invoked via selection.call. For example, to render a brush:
svg.append("g")
.attr("class", "brush")
.call(d3.brush().on("brush", brushed));
在内部,画笔使用 selection.on 绑定拖动所需的事件监听器。监听器使用名称 .brush
,因此你可以按如下方式解除绑定画笔事件监听器:
¥Internally, the brush uses selection.on to bind the necessary event listeners for dragging. The listeners use the name .brush
, so you can subsequently unbind the brush event listeners as follows:
group.on(".brush", null);
画笔还会创建显示画笔选择和接收交互输入事件所需的 SVG 元素。你可以根据需要添加、删除或修改这些元素以更改画笔外观;你还可以应用样式表来修改画笔外观。二维画笔的结构如下:
¥The brush also creates the SVG elements necessary to display the brush selection and to receive input events for interaction. You can add, remove or modify these elements as desired to change the brush appearance; you can also apply stylesheets to modify the brush appearance. The structure of a two-dimensional brush is as follows:
<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。
¥The overlay rect covers the brushable area defined by brush.extent. The selection rect covers the area defined by the current brush selection. The handle rects cover the edges and corners of the brush selection, allowing the corresponding value in the brush selection to be modified interactively. To modify the brush selection programmatically, use brush.move.
brush.move(group, selection, event) {#brush_move}
示例 · 源代码 · 将画笔的活动选择设置为指定组,该组必须是 SVG G 元素 中的 selection 或 transition。选择集必须定义为数字数组,或者设置为 null 以清除画笔选择集。对于 二维画笔,它必须定义为 [[x0, y0], [x1, y1]],其中 x0 为 x 轴的最小值,y0 为 y 轴的最小值,x1 为 x 轴的最大值,y1 为 y 轴的最大值。对于 x-brush,它必须定义为 [x0, x1];对于 y-brush,必须将其定义为 [y0, y1]。选择集也可以指定为返回此类数组的函数;如果是函数,则为每个选定元素调用该函数,并传递当前数据 d
和索引 i
,以 this
上下文作为当前 DOM 元素。返回的数组定义了该元素的画笔选择。
¥Examples · Source · Sets the active selection of the brush on the specified group, which must be a selection or a transition of SVG G elements. The selection must be defined as an array of numbers, or null to clear the brush selection. For a two-dimensional brush, it must be defined as [[x0, y0], [x1, y1]], where x0 is the minimum x-value, y0 is the minimum y-value, x1 is the maximum x-value, and y1 is the maximum y-value. For an x-brush, it must be defined as [x0, x1]; for a y-brush, it must be defined as [y0, y1]. The selection may also be specified as a function which returns such an array; if a function, it is invoked for each selected element, being passed the current datum d
and index i
, with the this
context as the current DOM element. The returned array defines the brush selection for that element.
brush.clear(group, event) {#brush_clear}
示例 · 源代码 · brush.move 的别名,选择为空。
¥Examples · Source · An alias for brush.move with the null selection.
brush.extent(extent) {#brush_extent}
示例 · 源代码 · 如果指定了 extent,则将可刷取的范围设置为指定的点数组 [[x0, y0], [x1, y1]],其中 [x0, y0] 表示左上角,[x1, y1] 表示右下角,并返回此画笔。范围也可以指定为返回此类数组的函数;如果是函数,则为每个选定元素调用该函数,并传递当前数据 d
和索引 i
,以 this
上下文作为当前 DOM 元素。如果未指定范围,则返回当前范围访问器,默认为:
¥Examples · Source · If extent is specified, sets the brushable extent to the specified array of points [[x0, y0], [x1, y1]], where [x0, y0] is the top-left corner and [x1, y1] is the bottom-right corner, and returns this brush. The extent may also be specified as a function which returns such an array; if a function, it is invoked for each selected element, being passed the current datum d
and index i
, with the this
context as the current DOM element. If extent is not specified, returns the current extent accessor, which defaults to:
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 中,对于 SVG 元素,element.clientWidth 和 element.clientHeight 为零!)
¥This default implementation requires that the owner SVG element have a defined viewBox, or width and height attributes. Alternatively, consider using element.getBoundingClientRect. (In Firefox, element.clientWidth and element.clientHeight is zero for SVG elements!)
画笔范围决定了不可见覆盖层的大小,并限制了画笔选择;画笔选择不能超出画笔范围。
¥The brush extent determines the size of the invisible overlay and also constrains the brush selection; the brush selection cannot go outside the brush extent.
brush.filter(filter) {#brush_filter}
示例 · 源代码 · 如果指定了 filter,则将 filter 设置为指定的函数并返回画笔。如果未指定 filter,则返回当前滤镜,默认为:
¥Examples · Source · If filter is specified, sets the filter to the specified function and returns the brush. If filter is not specified, returns the current filter, which defaults to:
function filter(event) {
return !event.ctrlKey && !event.button;
}
如果过滤器返回 false,则忽略启动事件,并且不会启动任何画笔手势。因此,过滤器决定忽略哪些输入事件。默认过滤器会忽略辅助按钮上的鼠标按下事件,因为这些按钮通常用于其他目的,例如上下文菜单。
¥If the filter returns falsey, the initiating event is ignored and no brush gesture is started. Thus, the filter determines which input events are ignored. The default filter ignores mousedown events on secondary buttons, since those buttons are typically intended for other purposes, such as the context menu.
brush.touchable(touchable) {#brush_touchable}
源代码 · 如果指定了 touchable,则将触摸支持检测器设置为指定的函数并返回画笔。如果未指定 touchable,则返回当前的触摸支持检测器,默认为:
¥Source · If touchable is specified, sets the touch support detector to the specified function and returns the brush. If touchable is not specified, returns the current touch support detector, which defaults to:
function touchable() {
return navigator.maxTouchPoints || ("ontouchstart" in this);
}
仅当画笔为 applied 时,检测器返回相应元素的真值时,才会注册触摸事件监听器。默认检测器适用于大多数支持触摸输入的浏览器,但并非所有浏览器都适用;例如,Chrome 的移动设备模拟器检测失败。
¥Touch event listeners are only registered if the detector returns truthy for the corresponding element when the brush is applied. The default detector works well for most browsers that are capable of touch input, but not all; Chrome’s mobile device emulator, for example, fails detection.
brush.keyModifiers(modifiers) {#brush_keyModifiers}
源代码 · 如果指定了 modifiers,则设置笔刷在刷动过程中是否监听按键事件,并返回此笔刷。如果未指定 modifiers,则返回当前行为,默认为 true。
¥Source · If modifiers is specified, sets whether the brush listens to key events during brushing and returns the brush. If modifiers is not specified, returns the current behavior, which defaults to true.
brush.handleSize(size) {#brush_handleSize}
源代码 · 如果指定了 size,则将密度估算器的大小设置为指定的边界并返回估算器。如果未指定大小,则返回当前句柄大小,默认为 6。此方法必须在对选定内容调用 应用画笔 之前调用;更改句柄大小不会影响之前渲染的画笔。
¥Source · If size is specified, sets the size of the brush handles to the specified number and returns the brush. If size is not specified, returns the current handle size, which defaults to six. This method must be called before applying the brush to a selection; changing the handle size does not affect brushes that were previously rendered.
brush.on(typenames, listener) {#brush_on}
源代码 · 如果指定了 listener,则为指定的 typenames 设置事件监听器并返回画笔。如果已为相同类型和名称注册了事件监听器,则在添加新监听器之前,会先移除现有监听器。如果 listener 为 null,则移除指定 typenames 的当前事件监听器(如果有)。如果未指定 listener,则返回第一个当前已分配的、与指定 typenames 匹配的监听器(如果有)。当指定事件被调度时,每个监听器都将使用与 selection.on 监听器相同的上下文和参数进行调用:当前事件 event
和数据 d
,以 this
上下文作为当前 DOM 元素。
¥Source · If listener is specified, sets the event listener for the specified typenames and returns the brush. If an event listener was already registered for the same type and name, the existing listener is removed before the new listener is added. If listener is null, removes the current event listeners for the specified typenames, if any. If listener is not specified, returns the first currently-assigned listener matching the specified typenames, if any. When a specified event is dispatched, each listener will be invoked with the same context and arguments as selection.on listeners: the current event event
and datum d
, with the this
context as the current DOM element.
typenames 是一个字符串,包含一个或多个用空格分隔的 typename。每个类型名称都是一种类型,后面可以跟一个句点 (.
) 和一个名称,例如 brush.foo
和 brush.bar
;该名称允许为同一类型注册多个监听器。类型必须是以下之一:
¥The typenames is a string containing one or more typename separated by whitespace. Each typename is a type, optionally followed by a period (.
) and a name, such as brush.foo
and brush.bar
; the name allows multiple listeners to be registered for the same type. The type must be one of the following:
start
- 在画笔手势开始时,例如鼠标按下时。¥
start
- at the start of a brush gesture, such as on mousedown.brush
- 当画笔移动时,例如鼠标移动时。¥
brush
- when the brush moves, such as on mousemove.end
- 在画笔手势结束时,例如鼠标释放时。¥
end
- at the end of a brush gesture, such as on mouseup.
更多信息请参阅 dispatch.on 和 画笔事件。
¥See dispatch.on and brush events for more.
brushSelection(node)
示例 · 源代码 · 返回指定节点的当前画笔选择。在内部,元素的画笔状态存储为 element.__brush;但是,你应该使用此方法而不是直接访问它。如果给定节点没有选择,则返回 null。否则,将选择定义为数字数组。对于 二维画笔,其值为 [[x0, y0], [x1, y1]],其中 x0 为 x 轴的最小值,y0 为 y 轴的最小值,x1 为 x 轴的最大值,y1 为 y 轴的最大值。对于 x-brush,它是 [x0, x1];对于 y-brush,其值为 [y0, y1]。
¥Examples · Source · Returns the current brush selection for the specified node. Internally, an element’s brush state is stored as element.__brush; however, you should use this method rather than accessing it directly. If the given node has no selection, returns null. Otherwise, the selection is defined as an array of numbers. For a two-dimensional brush, it is [[x0, y0], [x1, y1]], where x0 is the minimum x-value, y0 is the minimum y-value, x1 is the maximum x-value, and y1 is the maximum y-value. For an x-brush, it is [x0, x1]; for a y-brush, it is [y0, y1].
画笔事件
¥Brush events
调用 画笔事件监听器 时,它会接收当前的画笔事件。事件对象暴露了几个字段:
¥When a brush event listener is invoked, it receives the current brush event. The event object exposes several fields:
target
- 相关的 画笔行为。¥
target
- the associated brush behavior.type
- 字符串“start”、“brush”或“end”;参见 brush.on。¥
type
- the string “start”, “brush” or “end”; see brush.on.selection
- 当前 画笔选择。¥
selection
- the current brush selection.sourceEvent
- 底层输入事件,例如 mousemove 或 touchmove。¥
sourceEvent
- the underlying input event, such as mousemove or touchmove.mode
- 字符串“drag”、“space”、“handle”或“center”;画笔模式。¥
mode
- the string “drag”, “space”, “handle” or “center”; the mode of the brush.