32

D3 イベントとディスパッチ関数の使い方がわかりません。私が取り組んできたグラフの例は、「凡例付きの縦棒グラフ」です。

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

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

4

2 に答える 2

59

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

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

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

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

凡例のマウスオーバーで対応するバーを選択する方法がわからない場合は、通常、いくつかのオプションがあります。最も簡単な方法は、凡例要素の数と rect 要素の数が同じであり、それらが同じ順序であると仮定して、インデックスで選択することです。その場合、ローカル変数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 属性を生成したため、不自然です (この場合、インデックスによる選択の最初の手法を使用する方が簡単で高速です)。より現実的な例は、データに name プロパティがある場合です。d.name次に、id 属性を生成するために使用し、同様に id で選択できます。一意の ID を生成したくない場合は、他の属性またはクラスで選択することもできます。

于 2012-03-27T03:48:06.607 に答える
6

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

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

.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
    ) 
于 2013-01-20T23:28:15.353 に答える