web-dev-qa-db-ja.com

D3イベントを適切に追加して使用する方法は?

D3イベントとディスパッチ関数の使用を理解できません。私が取り組んでいるチャートの例は、「 凡例付きの縦棒グラフ 」と呼ばれています。

グラフと凡例の描画は簡単でしたが、グラフの右側にある相関テキストの凡例の上にマウスを置くと、各バーを強調表示する機能を追加したいと思います。

イベントのドキュメントをすべて読み、いくつかの例を見てきましたが、そのほとんどはかなり複雑ですが、何かが欠けているようです。対応する垂直バーの色を自動的に変更するイベントをディスパッチするテキスト凡例のマウスオーバー機能を最適に実現する方法を知っている人はいますか?

この質問は、d3-js Googleグループの 投稿したもの に似ています。私がそこに書いたものを複製せずに、おそらくd3.dispatchを望まないことを繰り返します。これは、カスタムイベントの抽象化(ブラシや動作など)を対象としています。ネイティブイベントを使用する方が簡単です。

凡例でマウスオーバー時に対応するバーの色を変更する場合は、問題をステップに分けます:

  1. 凡例上でマウスオーバーを検出します。
  2. 対応するバーを選択します。
  3. バーの塗りつぶし色を変更します。

まず、 selection.on を使用して、凡例要素の「マウスオーバー」イベントをリッスンします。マウスが凡例要素を通過すると、リスナー関数が呼び出され、データ(d)とインデックス(i)の2つの引数で呼び出されます。 d3.select を使用して、この情報を使用して対応するバーを選択できます。最後に、 selection.style を使用して、「塗りつぶし」スタイルを新しい色に変更します。

凡例のマウスオーバーで対応するバーを選択する方法がわからない場合、通常、いくつかのオプションがあります。最も簡単なのは、凡例要素の数と長方形要素の数が同じで、同じ順序であると仮定して、インデックスで選択することです。その場合、ローカル変数rectにrect要素が含まれている場合、次のように言えます。

function mouseover(d, i) {
  d3.select(rect[0][i]).style("fill", "red");
}

インデックスに依存したくない場合、別のオプションは、同一のデータに基づいて一致するバーをスキャンすることです。これは selection.filter を使用します:

function mouseover(d, i) {
  rect.filter(function(p) { return d === p; }).style("fill", "red");
}

さらに別のオプションは、各四角形に一意のIDを付与し、IDで選択することです。たとえば、初期化時に次のように言うことができます。

rect.attr("id", function(d, i) { return "rect-" + i; });

次に、マウスオーバー時にIDで四角形を選択できます。

function mouseover(d, i) {
  d3.select("#rect-" + i).style("fill", "red");
}

インデックスを使用してid属性を生成したため、上記の例は不自然です(この場合、インデックスによる選択の最初の手法を使用する方が簡単で高速です)。より現実的な例は、データに名前プロパティがある場合です。次に、d.nameを使用してid属性を生成し、同様にidで選択します。一意のIDを生成したくない場合は、他の属性またはクラスで選択することもできます。

60
mbostock

マイクの答えは素晴らしいです。

私が描いていたグリッドのセルを選択するためにこれを使用しました:

.on('click', (d, i) ->
      console.log("X:" + d.x, "Y:" + d.y) #displays the cell x y location
      d3.select(this).style("fill", "red");

そのため、データを入力するときに、イベントリスナーを追加し、d3.select(this)を使用します。

以下のコンテキストのコードを参照してください。

 vis.selectAll("rect")
    .data(singleArray)
    .enter().append("svg:rect")
    .attr("stroke", "none")
    .attr("fill", (d) -> 
      if d.lifeForm
        return "green" 
      else
        return "white")
    .attr("x", (d) -> xs(d.x))
    .attr("y", (d) -> ys(d.y))
    .attr("width", cellWidth)
    .attr("height", cellHeight)
    .on('click', (d, i) ->
      console.log("X:" + d.x, "Y:" + d.y)
      d3.select(this).style("fill", "red");
      return
    ) 
6
ChickenFur