71

D3で力指向グラフに取り組んでいます。他のすべてのノードとリンクを不透明度を低く設定して、マウスオーバーしたノード、そのリンク、およびその子ノードを強調表示したいと思います。

この例、http://jsfiddle.net/xReHA/では、すべてのリンクとノードをフェードアウトしてから、接続されたリンクをフェードインすることができますが、これまでのところ、エレガントにフェードインすることはできませんでした。現在マウスオーバーされたノードの子である接続されたノード。

これは、コードの主要な機能です。

function fade(opacity) {
    return function(d, i) {
        //fade all elements
        svg.selectAll("circle, line").style("opacity", opacity);

        var associated_links = svg.selectAll("line").filter(function(d) {
            return d.source.index == i || d.target.index == i;
        }).each(function(dLink, iLink) {
            //unfade links and nodes connected to the current node
            d3.select(this).style("opacity", 1);
            //THE FOLLOWING CAUSES: Uncaught TypeError: Cannot call method 'setProperty' of undefined
            d3.select(dLink.source).style("opacity", 1);
            d3.select(dLink.target).style("opacity", 1);
        });
    };
}

Uncaught TypeError: Cannot call method 'setProperty' of undefinedsource.targetからロードした要素に不透明度を設定しようとすると、エラーが発生します。これはそのノードをd3オブジェクトとしてロードする正しい方法ではないと思いますが、リンクのターゲットまたはソースに一致するノードを見つけるためにすべてのノードを再度繰り返すことなく、ノードをロードする別の方法を見つけることはできません。パフォーマンスを合理的に保つために、必要以上にすべてのノードを反復処理したくありません。

http://mbostock.github.com/d3/ex/chord.htmlからのリンクをフェードする例を取り上げました。

ここに画像の説明を入力してください

ただし、接続されている子ノードを変更する方法は示されていません。

これを解決または改善する方法についての良い提案は、猛烈に賛成されます:)

4

1 に答える 1

93

エラーは、これらのデータオブジェクトに関連付けられたDOM要素ではなく、データオブジェクト(d.sourceおよびd.target)を選択しているためです。

行の強調表示は機能していますが、おそらく次のようにコードを1つの反復に結合します。

 link.style("opacity", function(o) {
   return o.source === d || o.target === d ? 1 : opacity;
 });

各ノードの隣接ノードを知る必要があるため、隣接ノードの強調表示は難しくなります。ノードの配列とリンクの配列としてすべてを持っているため、この情報を現在のデータ構造で決定するのはそれほど簡単ではありません。DOMを少し忘れて、2つのノードが隣接aしているかどうかをどのように判断するかを自問してみてください。b

function neighboring(a, b) {
  // ???
}

これを行うための費用のかかる方法は、すべてのリンクを反復処理して、aとbを接続するリンクがあるかどうかを確認することです。

function neighboring(a, b) {
  return links.some(function(d) {
    return (d.source === a && d.target === b)
        || (d.source === b && d.target === a);
  });
}

(これは、リンクが無向であることを前提としています。前方に接続されたネイバーのみを強調表示する場合は、ORの後半を削除します。)

これを頻繁に実行する必要がある場合、これを計算するより効率的な方法は、aとbが隣接しているかどうかをテストするための一定時間のルックアップを可能にするマップまたはマトリックスを用意することです。例えば:

var linkedByIndex = {};
links.forEach(function(d) {
  linkedByIndex[d.source.index + "," + d.target.index] = 1;
});

今、あなたは言うことができます:

function neighboring(a, b) {
  return linkedByIndex[a.index + "," + b.index];
}

したがって、ノードを反復処理して、不透明度を正しく更新できるようになりました。

node.style("opacity", function(o) {
  return neighboring(d, o) ? 1 : opacity;
});

(のすべてのノードにセルフリンクを設定するか、スタイルを計算するときに直接linkedByIndexテストするか、!important cssスタイルを使用して、マウスオーバーリンク自体を特殊なケースにすることもできます。)d:hover

コードで最後に変更するのは、不透明度ではなく塗りつぶし不透明度とストローク不透明度を使用することです。これらははるかに優れたパフォーマンスを提供するためです。

于 2012-01-08T18:57:34.570 に答える