d3-brush
笔刷是使用指向手势(例如通过点击并拖动鼠标)的一维或二维选定区域的交互式规范。笔刷通常用于选择离散元素,例如散点图中的点或桌面上的文件。它也可用于放大感兴趣的区域,或为交叉过滤数据或实时直方图选择连续区域:
d3-brush模块使用SVG实现了鼠标和触摸事件的brushing。点击并拖动笔刷选区来翻译选区。点击并拖动选区手柄来移动选区相应的边(或多条边)。点击并拖动不可见的覆盖层来定义一个新的brush选区,或者在按住META(⌘)键的同时单击可刷区域内的任意位置。按住ALT(⌥)键的同时移动笔刷,使其围绕其中心重新定位,同时按住SPACE锁定当前笔刷尺寸,仅允许平移。
笔刷也支持程序控制。例如,你可以监听结束事件,然后使用brush.move初始化一个过渡将选区附着到语义边界:
或者,当你在当前选区外单击时,你可以使笔刷重新居中:
Installing
如果你使用npm,请键入npm install d3-
brush。否则,请下载最新版本。你也可以直接从d3js.org加载,作为standalone library(独立库)或D3 4.0(为了更好的使用,你也会想使用d3-scale和d3-selection,但它们并不是完全依赖的)的一部分来使用。支持AMD,CommonJS和vanilla环境。在vanilla环境下,会输出一个全局的d3
:
<script src="https://d3js.org/d3-color.v1.min.js"></script>
<script src="https://d3js.org/d3-dispatch.v1.min.js"></script>
<script src="https://d3js.org/d3-ease.v1.min.js"></script>
<script src="https://d3js.org/d3-interpolate.v1.min.js"></script>
<script src="https://d3js.org/d3-timer.v1.min.js"></script>
<script src="https://d3js.org/d3-selection.v1.min.js"></script>
<script src="https://d3js.org/d3-transition.v1.min.js"></script>
<script src="https://d3js.org/d3-drag.v1.min.js"></script>
<script src="https://d3js.org/d3-brush.v1.min.js"></script>
<script>
var brush = d3.brush();
</script>
API Reference
d3.brush()
创建一个新的二维笔刷。
d3.brushX()
沿x维度创建一个新的一维笔刷。
d3.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)
设置给定group上笔刷的活动selection,其必须是SVG中G元素的一个选集或过渡。selection必须定义为一个数字数组,或者null来清除笔刷选区。对于二维笔刷,其必须定义为[[x0, y0], [x1, y1]],其中x0为最小的x值,y0为最小的y值,x1为最大的x值,而y1为最大的y值。对于x-brush,其必须定义为 [x0, x1],对于y-brush,其必须定义为[y0, y1]。selection也可以定义为一个函数,返回一个数组;如果为函数,则将为每个选择的元素调用,传入当前数据d
和索引i
,并将this
上下文作为当前的DOM元素。返回的数组定义了该元素的笔刷选区。
brush.extent([extent])
如果指定了extent,则设置可刷区域为给定的点数组[[x0, y0], [x1, y1]],其中[x0, y0]为左上角,[x1, y1]为右下角,并返回此笔刷。extent也可以指定为一个函数,返回类似的一个数组;如果为函数,则将为每个选择的元素调用,传入当前数据d
和索引i
,并将this
上下文作为当前的DOM元素。如果不指定extent,则返回当前的extent accessor,默认为:
function extent() {
var svg = this.ownerSVGElement || this;
return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
}
此默认实现需要所有者SVG元素定义了宽度和高度属性,而不是(例如)依赖于CSS属性或viewBox属性;SVG不提供检索初始viewport大小的编程方法。或者,考虑使用element.getBoundingClientRect方法。(在火狐浏览器中,SVG元素的element.clientWidth和element.clientHeight为0!)
笔刷区域定义了不可见覆盖层的大小并限制笔刷选区;笔刷选区不能超过笔刷区域。
brush.filter([filter])
如果指定了filter,则设置过滤器为给定的函数并返回此笔刷。如果不指定filter,则返回当前的过滤器,默认为:
function filter() {
return !event.button;
}
如果过滤器返回false,则启动事件会被忽略且不会启动笔刷手势。因此过滤器定义了忽略哪个输入事件。默认的过滤器忽略了辅助按钮上的mousedown事件,因为这些按钮通常用于其他用途,例如上下文菜单。
brush.handleSize([size])
如果指定了size,则设置笔刷手柄为给定值并返回此笔刷。如果不指定size,则返回当前的手柄大小,默认为6。此方法必须在将笔刷应用于选集前调用;改变手柄的大小不会影响以前渲染的笔刷。
brush.on(typenames[, listener])
如果指定了listener,则为给定的typenames设置事件listener,并返回此笔刷。如果已经注册了同类型及名称的事件监听器,则在添加新监听器前会移除已有监听器。如果listener为null,则移除给定typenames上的当前监听器(如果有的话)。如果不指定listener,则返回第一个匹配typenames的监听器(如果有的话)。当指定事件派发时,将使用和selection.on相同的上下文及参数调用每个listener:当前数据d
和索引i
,并将this
上下文作为当前的DOM元素。
typenames是一个由空格分隔的包含一个或多个typename的字符串。每个typename都是一个type,可以选择跟一个句点(.
)和名称,如brush.foo
和brush.bar
;该名称允许为同一type注册多个监听器。type必须为下列之一:
start
- 在笔刷手势开始时,如mousedownbrush
- 当笔刷移动时,如mousemoveend
- 在笔刷手势结束时,如mouseup
另请参阅dispatch.on和Brush Events了解更多。
d3.brushSelection(node)
返回给定node的当前笔刷选区。在内部,元素的笔刷状态存储为element.__brush;但是你应该使用此方法而不是直接访问。如果给定node没有选区,则返回null。否则,选区定义为一个数字数组。对于二维笔刷,其为[[x0, y0], [x1, y1]],其中x0为最小的x值,y0为最小的y值,x1为最大的x值,而y1为最大的y值。对于x-brush,其为 [x0, x1],对于y-brush,其为[y0, y1]。
Brush Events
当一个笔刷事件监听器调用时,d3.event将设置为当前笔刷事件。event对象会暴露一些字段: