コンテンツへスキップ

d3-brush

ブラッシングとは、マウスのクリック&ドラッグなどのポインティングジェスチャを使用して、1次元または2次元の選択領域をインタラクティブに指定することです。ブラッシングは、散布図の点やデスクトップ上のファイルなど、離散的な要素を選択するために頻繁に使用されます。また、関心のある領域にズームインしたり、クロスフィルタリングデータやライブヒストグラムのために連続領域を選択するためにも使用できます。

Mona Lisa Histogram

d3-brushモジュールは、SVGを使用して、マウスとタッチイベントに対するブラッシングを実装します。ブラシ選択をクリック&ドラッグして選択を移動します。選択ハンドルの一つをクリック&ドラッグして、選択の対応する辺(または辺々)を移動します。非表示のオーバーレイをクリック&ドラッグして新しいブラシ選択を定義するか、META(⌘)キーを押しながらブラッシング可能な領域内のどこをクリックします。ALT(⌥)キーを押しながらブラシを移動すると、中心を中心に再配置されます。SPACEキーを押しながらブラシを移動すると、現在のブラシのサイズがロックされ、移動のみが可能になります。

ブラシは、プログラムによる制御もサポートしています。endイベントをリスンし、brush.moveを使用して遷移を開始して、ブラシ選択をセマンティック境界にスナップすることができます。

Brush Snapping

現在の選択の外側をクリックすると、ブラシが再中心化されるようにすることもできます。

Click-to-Recenter

brush()

· ソースコード · 新しい2次元ブラシを作成します。

brushX()

· ソースコード · x軸に沿った新しい1次元ブラシを作成します。

brushY()

ソースコード · y軸に沿った新しい1次元ブラシを作成します。

brush(group)

· ソースコード · 指定されたgroupにブラシを適用します。groupは、SVGのG要素選択でなければなりません。この関数は通常直接呼び出されることはなく、代わりにselection.callを介して呼び出されます。例えば、ブラシを描画するには

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

内部的には、ブラシはselection.onを使用して、ドラッグに必要なイベントリスナーをバインドします。リスナーは.brushという名前を使用するため、その後で次のようにブラシイベントリスナーをunbindできます。

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

ブラシは、ブラシ選択を表示し、インタラクションのための入力イベントを受信するために必要なSVG要素も作成します。ブラシの外観を変更するために、これらの要素を追加、削除、または変更できます。スタイルシートを適用してブラシの外観を変更することもできます。2次元ブラシの構造は次のとおりです。

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>

オーバーレイのrectは、brush.extentで定義されたブラッシング可能な領域をカバーします。選択rectは、現在のブラシ選択で定義された領域をカバーします。ハンドルのrectは、ブラシ選択の辺と角をカバーし、ブラシ選択の対応する値をインタラクティブに変更できます。ブラシ選択をプログラムで変更するには、brush.moveを使用します。

brush.move(group, selection, event)

· ソースコード · 指定されたgroupのブラシのアクティブなselectionを設定します。groupは、SVGのG要素選択または遷移でなければなりません。selectionは、数値の配列、またはブラシ選択をクリアするためのnullとして定義する必要があります。2次元ブラシの場合、[[x0, y0], [x1, y1]]として定義する必要があります。ここで、x0は最小のx値、y0は最小のy値、x1は最大のx値、y1は最大のy値です。xブラシの場合、[x0, x1]として定義する必要があります。yブラシの場合、[y0, y1]として定義する必要があります。selectionは、そのような配列を返す関数として指定することもできます。関数の場合は、選択された各要素に対して呼び出され、現在のデータdとインデックスiが渡され、thisコンテキストは現在のDOM要素になります。返された配列はその要素のブラシ選択を定義します。

brush.clear(group, event)

· ソースコード · null選択を使用したbrush.moveのエイリアスです。

brush.extent(extent)

· ソースコード · extentが指定されている場合、ブラッシング可能な範囲を指定された点の配列[[x0, y0], [x1, y1]]に設定し、このブラシを返します。ここで、[x0, y0]は左上の角、[x1, y1]は右下の角です。extentは、そのような配列を返す関数として指定することもできます。関数の場合は、選択された各要素に対して呼び出され、現在のデータdとインデックスiが渡され、thisコンテキストは現在のDOM要素になります。extentが指定されていない場合、現在の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要素に対して0になります!)

ブラシの範囲は、非表示のオーバーレイのサイズを決定し、ブラシの選択も制限します。ブラシの選択は、ブラシの範囲の外に出ることはできません。

brush.filter(filter)

· ソースコード · filter が指定されている場合、指定された関数にフィルターを設定し、ブラシを返します。filter が指定されていない場合、現在のフィルターを返します。デフォルトは

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

フィルターが偽の値を返す場合、開始イベントは無視され、ブラシジェスチャーは開始されません。したがって、フィルターはどの入力イベントを無視するかを決定します。デフォルトのフィルターは、セカンダリボタンのマウスダウンイベントを無視します。これらのボタンは通常、コンテキストメニューなど、他の目的で使用されるためです。

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 が指定されていない場合、現在のハンドルサイズを返します。デフォルトは6です。このメソッドは、ブラシを選択に適用する前に呼び出す必要があります。ハンドルサイズを変更しても、既にレンダリングされたブラシには影響しません。

brush.on(typenames, listener)

ソースコード · listener が指定されている場合、指定されたtypenamesにイベントlistenerを設定し、ブラシを返します。同じタイプと名前でイベントリスナーが既に登録されている場合、新しいリスナーを追加する前に既存のリスナーが削除されます。listener がnullの場合、指定されたtypenamesの現在のイベントリスナーを削除します(存在する場合)。listener が指定されていない場合、指定されたtypenamesに一致する現在割り当てられている最初のリスナーを返します(存在する場合)。指定されたイベントがディスパッチされると、各listener は、selection.onリスナーと同じコンテキストと引数で呼び出されます。現在のイベントeventとデータムdで、thisコンテキストは現在のDOM要素になります。

typenamesは、空白で区切られた1つ以上のtypenameを含む文字列です。各typenametypeであり、オプションでピリオド(.)とnameが続きます(例:brush.foobrush.bar)。nameを使用すると、同じtypeに対して複数のリスナーを登録できます。typeは次のいずれかである必要があります。

  • start - マウスダウン時など、ブラシジェスチャーの開始時。
  • brush - マウスムーブ時など、ブラシが移動するとき。
  • end - マウスアップ時など、ブラシジェスチャーの終了時。

dispatch.onブラシイベントの詳細については、を参照してください。

brushSelection(node)

· ソースコード · 指定されたnodeの現在のブラシ選択を返します。内部的には、要素のブラシ状態はelement.__brushとして保存されますが、直接アクセスするのではなく、このメソッドを使用する必要があります。指定されたnodeに選択がない場合、nullを返します。それ以外の場合は、selectionは数値の配列として定義されます。2次元のブラシの場合、[[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"。ブラシのモード。