6

私は関数型プログラミングのバックグラウンドがあり、原則として再帰を理解していますが、この知識をD3.js環境に変換することはできないようです。

以下に、ネストされたデータ構造の内容を単純に出力しようとする Hello World スクリプトがあります。他のスレッドに関するアドバイスに従って.filter、ノードのみを返すために使用できますが、この例を続けてネストされたアイテムを再帰的に出力するにはどうすればよいでしょうか?

<!DOCYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <script src="d3.v3.js"></script>

        <script>
            function draw(data)
            {
                "use strict";

                d3.select("body")
                    .selectAll("p")
                    .data(data)
                    .enter()
                    .append("p")
                    .text(function(d) {
                            if (d instanceof Array) {
                                return "WHAT DO I PUT HERE?";
                            }
                            else {
                                return d;
                            };
                        });
            }
        </script>
    </head>

    <body>
        Hello world

        <script>
            draw([1, [2, [1, 2, 3, 4] ], 3, 4, 5]);
        </script>
    </body>
</html>
4

2 に答える 2

2

これを行う簡単な方法は、再帰を避けることです! 典型的な D3.js のアプローチは、データを再帰して、レイアウトに必要な情報 (たとえば、子の合計サイズ、入れ子の深さの合計、各ノードの深さ) を決定してから、構造をフラット化し、計算された値をレイアウトに使用することです。 .

この優れた例は、このツリーの例で見つけることができます。ここでは、計算と平坦化が組み込み関数で処理されます。

var tree = d3.layout.tree()...

そうは言っても、レイアウトで直接再帰を実行するために必要な種類の選択体操に頭を悩ませたい場合は、そうすることができます。重要なのは、選択を行ってから、親のデータに基づいてデータを設定する必要があるということです。

以下の例では、便宜上 maxLevels をハードコーディングしましたが、ループに入る前にデータから計算することができます。

また、レイアウトについて非常に怠惰だったことにも注意してください。レイアウトを適切に行うには、開始前に各要素が少なくともいくつの子を持つかを最初に計算するために、データに再帰的なパスが必要だからです。ここでフィドルで遊ぶことができます。

var data = { children: [{
        txt: "a", children: [{
            txt: "aa", children: [{
                txt: "aaa"}, {
                txt: "aab"}]}, {
            txt: "ab"}]}, {
        txt: "b", children: [{
            txt: "ba"}, {
            txt: "bb"}, {
            txt: "bc"}]}, {
        txt: "c"}]};

var svg = d3.selectAll("svg");

svg.attr({ width: 500, height: 500});

var recurse = svg.selectAll("g.level0").data([data]).enter()
    .append("g").classed("level0", true);

var maxLevels = 4;
for (var level = 0; level < maxLevels; level++) {

    var nextLevel = level + 1;

    var next = svg.selectAll("g.level" + level).filter(function (d) {
        return d.children !== undefined;
    });

    next.selectAll("g.level" + nextLevel)
        .data(function (d) { return d.children; })
        .enter().append("g")
        .attr("class", function (d) {
            return "level" + nextLevel + " " + d.txt;
        })
        .attr("transform", function (d, i) {
            return "translate(" + (nextLevel * 25) + "," + (i * 10 * (5 - level) + 15) + ")";
        });

    next.selectAll("text.level" + nextLevel)
        .data(function (d) {  return d.children; })
        .enter().append("text")
        .classed("level" + level, true)
        .attr("x", function (d, i, j) {  return nextLevel * 25;  })
        .attr("y", function (d, i, j) {
            return j * (10 * (10 - level)) + (i+1) * 15;
        })
        .attr("fill", "black")
        .text(function (d) { return d.txt; });
}
于 2013-01-18T00:15:15.537 に答える