跳到內容

d3-brush

刷選是透過指標手勢(例如按住滑鼠並拖曳)來互動式設定一或二維選取區域。刷選通常用於選取離散元素,例如散佈圖中的點或桌面上的檔案。它也可以用於縮放感興趣的區域,或選取連續區域以進行 交叉過濾資料 或即時直方圖

Mona Lisa Histogram

d3-brush 模組使用 SVG 實作滑鼠和觸控事件的刷選功能。按住並拖曳刷選選取範圍以移動選取範圍。按住並拖曳其中一個選取範圍控制點以移動選取範圍的對應邊緣(或邊緣)。按住並拖曳隱形覆蓋層以定義新的刷選選取範圍,或按住 META (⌘) 鍵並按一下可刷選區域內的任何位置。移動刷選時按住 ALT (⌥) 鍵會讓刷選以其中心為基準重新定位,而按住 SPACE 則會鎖定目前的刷選大小,只允許移動。

刷選也支援程式控制。例如,你可以監聽 end 事件,然後使用 brush.move 啟動轉場,讓刷選選取範圍貼齊語義邊界

Brush Snapping

或者,你可以在按一下目前的選取範圍之外時讓刷選重新置中

Click-to-Recenter

brush()

範例 · 原始碼 · 建立一個新的二維刷選。

brushX()

範例 · 原始碼 · 沿著x維度建立新的單維度畫刷。

brushY()

原始碼 · 沿著y維度建立新的單維度畫刷。

brush(group)

範例 · 原始碼 · 將畫刷套用至指定的group,該group必須是 SVG G 元素選取。此函式通常不會直接呼叫,而是透過 selection.call 呼叫。例如,要呈現畫刷

js
svg.append("g")
    .attr("class", "brush")
    .call(d3.brush().on("brush", brushed));

在內部,畫刷會使用 selection.on 來繫結必要的拖曳事件監聽器。監聽器會使用名稱 .brush,因此您可以使用以下方式取消繫結畫刷事件監聽器

js
group.on(".brush", null);

畫刷也會建立顯示畫刷選取範圍和接收互動輸入事件所需的 SVG 元素。您可以視需要新增、移除或修改這些元素以變更畫刷外觀;您也可以套用樣式表來修改畫刷外觀。二維畫刷的結構如下

html
<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 元素selectiontransitionselection 必須定義為數字陣列,或 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,則傳回目前的範圍存取器,預設為

js
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,或 widthheight 屬性。或者,考慮使用 element.getBoundingClientRect。(在 Firefox 中,element.clientWidthelement.clientHeight 對 SVG 元素為零!)

畫筆範圍決定隱形疊加層的大小,並限制畫筆選取;畫筆選取無法超出畫筆範圍。

brush.filter(filter)

範例 · 原始碼 · 如果指定 filter,則將篩選器設定為指定函式,並傳回畫筆。如果未指定 filter,則傳回目前的篩選器,預設為

js
function filter(event) {
  return !event.ctrlKey && !event.button;
}

如果篩選器傳回偽值,則會略過啟動事件,且不會開始任何畫筆手勢。因此,篩選器決定略過哪些輸入事件。預設篩選器會略過次要按鈕上的 mousedown 事件,因為這些按鈕通常用於其他目的,例如內容選單。

brush.touchable(touchable)

原始碼 · 如果指定 touchable,則將觸控支援偵測器設定為指定函式,並傳回畫筆。如果未指定 touchable,則傳回目前的觸控支援偵測器,預設為

js
function touchable() {
  return navigator.maxTouchPoints || ("ontouchstart" in this);
}

只有當偵測器在 套用 畫筆時,對應元素傳回真值,才會註冊觸控事件監聽器。預設偵測器適用於大多數具備觸控輸入功能的瀏覽器,但並非全部;例如,Chrome 的行動裝置模擬器無法偵測。

brush.keyModifiers(modifiers)

原始碼 · 如果指定了 modifiers,則設定畫筆是否在繪製時監聽鍵盤事件,並傳回畫筆。如果未指定 modifiers,則傳回目前的行為,預設為 true。

brush.handleSize(size)

原始碼 · 如果指定了 size,則將畫筆控制項的大小設定為指定的數字,並傳回畫筆。如果未指定 size,則傳回目前的控制項大小,預設為六。這個方法必須在 將畫筆套用 到一個選取之前呼叫;變更控制項大小不會影響先前已呈現的畫筆。

brush.on(typenames, listener)

原始碼 · 如果指定了 listener,則設定指定 typenames 的事件 listener,並傳回畫筆。如果已經為同一個類型和名稱註冊了事件 listener,則在加入新的 listener 之前會移除現有的 listener。如果 listener 為 null,則移除指定 typenames 的目前事件 listener(如果有的話)。如果未指定 listener,則傳回目前指派給指定 typenames 的第一個 listener(如果有的話)。當指定的事件被觸發時,每個 listener 都會以與 selection.on listener 相同的內容和參數呼叫:目前的事件 event 和資料 d,其中 this 的內容為目前的 DOM 元素。

typenames 是包含一個或多個 typename 的字串,各 typename 以空白分隔。每個 typename 都是一個 type,後面可以選擇接一個句點 (.) 和一個 name,例如 brush.foobrush.barname 允許為同一個 type 註冊多個 listener。type 必須是下列其中一個

  • start - 在畫筆手勢開始時,例如在 mousedown 時。
  • brush - 當畫筆移動時,例如在 mousemove 上。
  • end - 在畫筆手勢結束時,例如在 mouseup 上。

請參閱 dispatch.on畫筆事件 以了解更多資訊。

brushSelection(node)

範例 · 來源 · 傳回指定 node 的目前畫筆選取範圍。在內部,元素的畫筆狀態儲存在 element.__brush 中;不過,您應該使用此方法,而不是直接存取它。如果給定的 node 沒有選取範圍,則傳回 null。否則,選取範圍會定義為一個數字陣列。對於 二維畫筆,它是 [[x0, y0], [x1, y1]],其中 x0 是最小 x 值,y0 是最小 y 值,x1 是最大 x 值,而 y1 是最大 y 值。對於 x 畫筆,它是 [x0, x1];對於 y 畫筆,它是 [y0, y1]。

畫筆事件

當呼叫 畫筆事件監聽器 時,它會接收目前的畫筆事件。event 物件公開多個欄位

  • target - 關聯的 畫筆行為
  • type - 字串 “start”、“brush” 或 “end”;請參閱 brush.on
  • selection - 目前的 畫筆選取範圍
  • sourceEvent - 基礎的輸入事件,例如 mousemove 或 touchmove。
  • mode - 字串 “drag”、“space”、“handle” 或 “center”;畫筆的模式。