簡介
Brushing是一個通過點擊或觸摸來選擇一個一維或二維區域的交互操作,比如可以通過點擊鼠標並移動. brush經常被用來選擇離散的元素比如散點圖中的點或桌面上的文件等。它也可以被用來放大選中的區域。
d3-brush模塊的實現基於鼠標和觸控事件以及SVG. 點擊並拖動來對選中的區域進行變換,點擊並拖拽brush邊緣來改變選中的范圍大小. 點擊並拖拽選中區域外側時開始一個新的brush區域,點擊並在按下META鍵或 ALT鍵拖動時會以點擊區域為中心進行區域選取,按下SPACE時或鎖定當前區域大小,此時僅允許移動變換.
安裝引用
如果你使用NPM, npm install d3-brush. 也可以從 d3js.org直接下載 最新版. 可以作為單獨的模塊 或 D3 4.0一部分使用. 也支持AMD, CommonJS, 和 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 參考
# d3.brush()
創建一個二維的brush.
# d3.brushX()
創建一個一維的 x-方向的brush.
# d3.brushY()
創建一個一維的 y-方向的brush.
# brush(group)
為指定的 group 應用brush, 一定是一個 選擇集,選擇集為SVG的G 元素. 這個方法可以間接調用, 也可以通過使用 selection.call來調用. 例如:
svg.append("g")
.attr("class", "brush")
.call(d3.brush().on("brush", brushed));
在內部,brush會使用 selection.on來綁定需要的拖拽事件監聽器,事件監聽器使用 .brush來表示這個事件監聽器是用來brush的, 你可以使用如下方法來取消brush的事件監聽器:
group.on(".brush", null);
brush會創建SVG元素來顯示選中的區域,你可以添加、刪除或按需改變這些元素的樣式,也可以通過樣式表來修改外觀. 二維的brush元素結構如code list 1所示:
<!--code list 1:-->
<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是被包含在一個g元素內部。使用class為overlay矩形來表示brush的范圍 brush.extent,即在這個區域內可繪制bursh,超出這個范圍就不能繪制bursh了。class為selection的矩形部分覆蓋了由 brush selection定義的區域. handle矩形表示四個邊框和四個角落(不可見),當鼠標接近區域邊緣時候可以拖動,實際上是鼠標移到了這些矩形上. 使用 brush.move來對brush進行編程設置.
# brush.move(group, selection)
為指定的group設置選中范圍,它通常用來初始化brush的范圍大小,這個group必須是一個選擇集 或一個SVG G元素的過渡 . selection 為一個數值類型的數組。對於, 對於 二維 brush,必須由 [[x0, y0], [x1, y1]]定義, x0和 y0 表示最小x和y值, x1和y1 表示最大x和y值,如上面code list 1中brush的范圍就是:[[289,189],[299,282]]. 對於 x-brush, 一定由 [x0, x1]定義; 對於 y-brush, 一定定義為 [y0, y1]. selection也可以是一個返回數組類型的方法. 如果是一個方法則會為每個選中的元素調用,並傳遞當前的數據d 和索引i, this 表示當前的DOM元素節點.
let brush = d3.brush();
let brushG = svg.append("g");
brushG.call(brush)
.call(brush.move,[[100,100],[250,250]]);//為brush定義一個初始的大小。
//也可以寫成
//brush.move(brushG,[[100,100],[250,250]]);
# brush.extent([extent])
如果 extent 指定,則設置可刷取的范圍,它必須在 brush(group) 調用,否則沒有效果,extent由 [[x0, y0], [x1, y1]]指定, [x0, y0] 表示左上角坐標, [x1, y1] 表示右下角坐標, 並返回brush. extent 也可以使用返回類似數組的函數; 如果是方法,則會為每個選中的元素調用,並傳遞當前的數據 d 和索引i, this 表示當前的DOM元素節點. 如果沒有指定 extent 則返回當前的范圍,默認如下:
function extent() {
var svg = this.ownerSVGElement || this;
return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];
}
設置可刷取的范圍
brush.extent([[100,50],[500,550]]);
brush的范圍為應用了brush的分組的最大覆蓋范圍,不能選中分組以外的元素。
# brush.filter([filter])
如果指定過濾器,則設置過濾器,以指定的函數返回的brush。如果未指定過濾器,返回當前的過濾器,其默認值為::
function filter() {
return !event.button;
}
如果返回false,則會忽略起始事件並不會啟動brush。這樣可以用來區別哪些事件不作為brush操作。默認的過濾器會忽略第二層按下鼠標事件,因為這些事件可能被用作其他目的。
# brush.handleSize([size])
如果指定了size 則設置brush柄的大小並返回brush,如果沒有指定則返回當前的handle尺寸,默認為6.這個是前面提到的handle rect的寬度或高度,當鼠標位於邊緣3之內的時候會啟動邊緣拖拽功能. 這個方法一定要在 應用brush到一個選擇集之前設置,即brush4個邊和4個角的緩沖區。改變handlesize不會對之前的brush有影響。
brush.handleSize(100);
# brush.on(typenames, [listener])
如果指定了 listener 則為brush設置指定類型的事件監聽器並返回brush. 如果之前已經指定過事件監聽器,則會覆蓋之前的事件監聽器. 如果listener 為 null, 則移除響應類型的時間監聽器. 如果 listener 沒有指定則返回第一個與事件類型匹配的事件監聽器.
typenames 是一個表示事件類型的字符串,多個類型可以使用空格隔開. 每個 typename 都是一個 type, 可以使用*.*指定類 brush.foo 和 brush.bar; 這樣可以為相同的事件類型指定不同的監聽器. 事件類型必須為如下中的一個:
start- 開始brush操作,比如鼠標按下.brush-當拖動brush區域進行選取時,比如鼠標拖動.end- 在選取結束時,比如鼠標抬起.
listener中的this為承載brush的G元素。
參考dispatch.on 和 Brush Events 獲取更多信息.
# d3.brushSelection(node)
返回指定節點的brush選擇,在內部元素的brush或以 element.__brush形式存儲; 但是你應該使用d3.brushSelection而不是通過直接訪問內部存儲來調用,如果給定的node沒有附加brush操作,則返回null. 此外 selection 被定義為一個數值數組. 對於 二維 brush, 它是[[x0, y0], [x1, y1]]這種形式, x0 和y0 表示最小x和y值, x1和 y1 表示最大x和y值, 對於x-brush, 表示為[x0, x1]; 對於 y-brush, 表示為[y0, y1].
Brush 事件
當 brush 事件監聽器 被調用時, d3.event 被設置為當前的brush事件. brush event 對象包括以下幾個屬性:
target- brush 事件的目標元素.就是brush本身type- 事件類型 “start”, “brush” or “end”;參考 brush.on.selection- 當前的 brush 選擇集.即,brush的范圍sourceEvent- 底層輸入事件, 比如 mousemove 或 touchmove.
//創建一個brush
let brush = d3.brush();
//brush.handleSize(100);
brush.on("end",()=>{
console.log(d3.event);
});
//創建一個G元素用於存放brush
let brushG = svg.append("g");
brush(brushG);
//還可以為brush設置一個初始的大小
brush.move(brushG,[[100,100],[250,250]]);
通過事件便可以通過編程方式控制Brush. 比如添加end 事件監聽器, 然后使用brush.move來設置brush范圍:
d3.brush on jsbin.com