无法使用d3层次结构构造d3树结构不平衡树

时间:2018-04-26 15:14:23

标签: d3.js tree

我正在尝试绘制不平衡树,如下所示

enter image description here

以下是代码:

var array = [ 'F', 'G', 'I', 'H', 'B', 'A', 'D', 'C', 'E' ];
var clusterLayout = d3.cluster().size([ 400, 200 ]);
var rootdata = addNode(array, null);
var root = d3.hierarchy(rootdata);
clusterLayout(root);
update(root);

function addNode(array, root) {
    var rootdata = {};
    array.forEach(function(d) {
        if (jQuery.isEmptyObject(rootdata)) {
            rootdata = {
                name : d,
                children : []
            };
        } else {
            var next = rootdata;
            var previous = null;
            while (next != null) {
                previous = next;
                if (next.name > d) {
                    next = next.children[0];
                } else {
                    if (next.children == null)
                        next = null;
                    else
                        next = next.children[1];
                }
            }
            if (previous.children == null) {
                previous.children=[];
            }
            if (previous.name > d) {
                previous.children[0] = {
                    name : d,
                    children : []
                };
            } else {
                if (previous.children[0] == null)
                    previous.children[0] = {};
                previous.children[1] = {
                    name : d,
                    children : []
                };
            }
        }
    });
    return rootdata;
}
function update(root) {
    var circles = d3.select('svg g.nodes').selectAll('circle.node').data(
            root.descendants());
    circles.enter().append('circle').classed('node', true).attr("fill", "white").attr(
            'cx', function(d) {
                return d.x;
            }).attr('cy', function(d) {
        return d.y;
    }).attr('r', 20);

    circles.enter().append("text").attr("dx", function(d) {
        return d.x;
    }).attr("dy", function(d) {
        return d.y;
    }).text(function(d) {
        return d.data.name
    }).attr("fill", "black").attr("font-size", "15px").attr("font-family",
            "sans-serif").attr("text-anchor", "middle");
    // Links
    d3.select('svg g.links').selectAll('line.link').data(root.links()).enter().append(
            'line').classed('link', true).attr('x1', function(d) {
        return d.source.x;
    }).attr("stroke", "black").attr('y1', function(d) {
        return d.source.y;
    }).attr('x2', function(d) {
        return d.target.x;
    }).attr('y2', function(d) {
        return d.target.y;
    });
}

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script> 
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.2.2/d3.js"></script>
<link rel="stylesheet" href="simple_tree.css">
</head>
<body>

    <svg width="1000" height="1000">
    <g transform="translate(80,80)">
      <g class="links"></g>
      <g class="nodes"></g>
    </g>
  </svg>
    <script type="application/javascript" src="/simple_tree.js"></script>
    <div id="tree-container"></div>
</body>
</html>

呈现为

enter image description here

问题是因为代码片段下方的 addNode方法中添加了emtpy节点。我无法添加子项[0] = null,这是错误的。但我不能添加子1右节点而不在0处添加子数组。我该怎样解决这个问题?

if (previous.children[0] == null)
        previous.children[0] = {};

1 个答案:

答案 0 :(得分:0)

如下所示,但无法移除最后一个空节点。

var array = [ 'F', 'G', 'I', 'H', 'B', 'A', 'D', 'C', 'E' ];
var clusterLayout = d3.cluster().size([ 400, 200 ]);
var rootdata = addNode(array, null);
var root = d3.hierarchy(rootdata);
clusterLayout(root);
update(root);

function addNode(array, root) {
    var rootdata = {};
    array.forEach(function(d) {
        if (jQuery.isEmptyObject(rootdata)) {
            rootdata = {
                name : d,
                children : []
            };
        } else {
            var next = rootdata;
            var previous = null;
            while (!jQuery.isEmptyObject(next) && next != null) {
                previous = next;
                if (next.name > d) {
                    next = next.children[0];
                } else {
                    if (next.children == null)
                        next = null;
                    else
                        next = next.children[1];
                }
            }
            if (previous.name > d) {
                previous.children[0] = {
                    name : d,
                    children : []
                };
            } else {
                if (previous.children[0] == null) {
                    previous.children[0] = {};
                    previous.children[1] = {
                        name : d,
                        children : []
                    };

                } else if (jQuery.isEmptyObject(previous.children[0])) {
                    previous.children[0] = {
                        name : d,
                        children : []
                    };
                } else {
                    previous.children[1] = {
                        name : d,
                        children : []
                    };
                }
            }
        }
    });
    return rootdata;
}
function update(root) {
    var circles = d3.select('svg g.nodes').selectAll('circle.node').data(
            root.descendants());
    circles.enter().append('circle').classed('node', true).attr("fill", "white").attr(
            'cx', function(d) {
                return d.x;
            }).attr('cy', function(d) {
        return d.y;
    }).attr('r', 20);

    circles.enter().append("text").attr("dx", function(d) {
        return d.x;
    }).attr("dy", function(d) {
        return d.y;
    }).text(function(d) {
        return d.data.name
    }).attr("fill", "black").attr("font-size", "15px").attr("font-family",
            "sans-serif").attr("text-anchor", "middle");
    // Links
    d3.select('svg g.links').selectAll('line.link').data(root.links()).enter().append(
            'line').classed('link', true).attr('x1', function(d) {
        return d.source.x;
    }).attr("stroke", "black").attr('y1', function(d) {
        return d.source.y;
    }).attr('x2', function(d) {
        return d.target.x;
    }).attr('y2', function(d) {
        return d.target.y;
    });
}

enter image description here