web-dev-qa-db-ja.com

NodeSizeを使用したノード間のD3ツリーレイアウトの分離

以下の図に示すように、長方形ノードは重なっているため、現在、長方形ノードを分離しようとしています。

enter image description here

私は見てみると、D3は nodeSize および separation メソッドを提供していることがわかりましたが、何らかの理由で機能しませんでした。

私はこれを見つけました ブログ投稿 問題について話していますが、彼は言います

サイズプロパティはノードには存在しないため、ノードのサイズを制御するプロパティになります。

ただし、nodeSizeメソッドがあることは明らかです。そのため、このメソッドを間違って使用しているだけで、ブログの投稿が古くなっているように感じます。ノードを長方形のサイズに整形し、ノードが互いに重ならないように均等に配置します。誰もがメソッドを適切に使用する方法を知っていますか?これらのメソッドに関するドキュメントはあまり説明されておらず、違いはありません。また、人々が木のノードサイズを変更したり、長方形のオブジェクトの分離が必要だったりする多くの例を見つけることができませんでした(円形のものに関するいくつかの例がありましたが、私はそれがあまりにも違うと感じています...)

関連するコードは次のとおりです。 JSFiddleの準備を試みます。

var margin = {top: 20, right: 120, bottom: 20, left: 120},
    height = 960 - margin.right - margin.left,
    width = 800 - margin.top - margin.bottom,
    rectW = 70;
    rectH = 30;
    //bbox = NaN,
    maxTextLength = 0;

var i = 0,
    duration = 750,
    root;


//paths from each node drawn initially here
//changed to d.x, d.y
var diagonal = d3.svg.diagonal()
    .projection(function(d) { return [d.x+rectW/2, d.y+rectH/2];
    //.projection(function(d) { return [d.x+bbox.getBBox().width/2, d.y+bbox.getBBox().height/2]; 
});

var tree = d3.layout.tree()
    .nodeSize([30,70])
    .separation(function(a, b) { return (a.parent == b.parent ? 1 : 2); })
    .size([width, height]);

var svg = d3.select("body")
            .append("svg")
              .attr("height","100%").attr("width","100%")
              .call(d3.behavior.zoom().on("zoom", redraw))
              .append("g")
                .attr("transform", "translate(" + margin.top + "," + margin.left + ")");
33
aug

UPDATE 05/04/2018:私の理解では、d3はより良くモジュール化するために(より良いために)大きく変化しました。この答えを探している人のために、これははるかに古いバージョンのd3(特にv3)を使用していました。

多くの調査結果は、 _d3-hierarchy_cluster.size() and cluster.nodeSize() の下のパッケージに関連しています。それを使用するように私の例を潜在的に更新します。ただし、歴史的な参考のために、私は下の部分をそのままにしておきます。


ここにjsFiddleがあります: http://jsfiddle.net/augburto/YMa2y/

編集:例を更新してCodepenに移動します。この例はjsFiddleにまだ存在しますが、Codepenはより優れたエディターを備えているようで、簡単に分岐できます。また、コンテンツの量を減らしたら、この回答にサンプルを直接追加しようとします。

http://codepen.io/augbog/pen/LEXZKK

この回答を更新しています。友達と話をして、sizenodeSizeのソースを見ました

_  tree.size = function(x) {
    if (!arguments.length) return nodeSize ? null : size;
    nodeSize = (size = x) == null;
    return tree;
  };

  tree.nodeSize = function(x) {
    if (!arguments.length) return nodeSize ? size : null;
    nodeSize = (size = x) != null;
    return tree;
  };
_

ツリーにsizeを設定すると、ツリーがその幅と高さに適合しなければならないように、固定サイズが設定されます。 nodeSizeを設定すると、ツリーは動的である必要があるため、ツリーのサイズがリセットされます。

sizeの後にnodeSizeを指定したとき、望んでいたものをほとんどオーバーライドしていました。

一番下の行nodeSizeを機能させたい場合は、ツリーのサイズを固定することはできません。サイズをnullに設定します。 sizeを宣言している場合は、nodeSizeを宣言しないでください。

編集:D3.jsは実際に ドキュメントを更新 。それが今よりずっと明確になったので、だれでもありがとう!

NodeSizeプロパティはtree.size専用です。 tree.nodeSizeを設定すると、tree.sizeがnullに設定されます。

これが私のツリーの外観です。また、ズーム機能と、テキストを長方形の中央に配置する方法も追加しました。

Picture where nodeSize is set at width of 100 and height of 30

44
aug

私は自分で掘り下げるまで受け入れられた答えを十分に理解していなかったので、私も見つけたものを共有すると思った...

.size()を使用していて、ノードが重複している場合は、代わりに.nodeSize()を使用します

受け入れられた答えで説明されているように、.size()はツリーの利用可能なサイズを設定します。 .nodeSize()を使用すると、各ノードがこれだけのスペースを確保する必要があるため、オーバーラップすることはありません。

最終的に私のために働いたコードは

_var nodeWidth = 300;
var nodeHeight = 75;
var horizontalSeparationBetweenNodes = 16;
var verticalSeparationBetweenNodes = 128;

var tree = d3.layout.tree()
    .nodeSize([nodeWidth + horizontalSeparationBetweenNodes, nodeHeight + verticalSeparationBetweenNodes])
    .separation(function(a, b) {
        return a.parent == b.parent ? 1 : 1.25;
    });
_

horizontalSeparationBetweenNodesverticalSeparationBetweenNodesがなければ、ノードのエッジは互いに接触していました。また、この.separation()を追加して、いとこノード間のスペースを減らしました。これは、ノードがかなり広く、多くのスペースが無駄になっていたためです。

注:これは、v4ではなくd3 v3用です

11
Danny Harding

D3はObservableを介して処理を行うようになりました。

ObservableでnodeSizeを設定し、

lineを探します:

main.variable(observer("tree")).define("tree", ["d3","dx","dy"],
function(d3,dx,dy){return(
d3.tree()

そして、追加された定数でノードサイズを設定

main.variable(observer("tree")).define("tree", ["d3","dx","dy"],
function(d3,dx,dy){return(
d3.tree().nodeSize([dx + 10, dy + 10])

または、古いD3アプローチを使用した他の回答で説明されているように、関数を使用してチャートサイズに値を設定します。

0
Cybernetic

まず、以前に投稿したすべての人に感謝します、純金。水平に描画されたツリーに関連するオフセットの問題に苦しんでいる可能性のある人のために、この投稿に追加したかった。

重要なのは、水平ツリーで.size()から.nodeSize()に切り替えると、ルートノードが(0,0)に位置するようにジャンプ/方向転換しているように見えることです。 d3.jsのドキュメントによれば、これは実際に当てはまります( https://github.com/d3/d3-hierarchy/blob/master/README.md#tree_nodeSize を参照)

ただし、調整するには、viewBoxの向きを変更する必要があります。つまり、.append your svgviewBoxを明示的に設定する必要があります。これが私の役に立つハックな小さなラインです...

svg = d3.select("#tree").append("svg")
            .attr("width", width + margin.right + margin.left)
            .attr("height", height + 0 + 0)
            .attr("viewBox", "0 "+(-1*(height-margin.top-margin.bottom)/2)+" "+width+" "+height)
            .append("g")
            .attr("transform", "translate("
                  + margin.left + "," + 0 + ")");
0
Kevin Gunn