【问题标题】:D3 V3 to D3 V4 Tree Array Reordered Wrong Using HierarchyD3 V3 到 D3 V4 树数组使用层次结构重新排序错误
【发布时间】:2017-11-07 06:58:47
【问题描述】:

这听起来可能比我预期的要复杂,但是,我正在从 D3 V3 切换到 D3 V4。我的所有其他图形和图表都非常容易转移,但是这个特定的(一棵树)从 d3.layout.tree 更改并简单地使用 .children() 函数然后设置节点/链接使用 d3.hierarchy() 的旧方法到新方法。我按照我在无数教程中看到的方式设置它。

我设置了 2 个不同的 Plunker。 这个在 D3 V3 中,并且以正确的数组顺序正常工作/显示: https://plnkr.co/edit/qXDWDGzhNIM2tTOoAXRa?p=preview

var tree = d3.layout.tree()
                .nodeSize([0, 75])
                .children(function(d) {
                    return d.subsidiaries;
                });

            var line = d3.svg.line().interpolate('step')
                .x(function(d) {
                    return d.x;
                })
                .y(function(d) {
                    return d.y - 12;
                });

            // Define 'div' for tooltips
            var div = d3.select('#tree')
                // Declare the tooltip div
                .append('div')
                // Apply the 'tooltip' class
                .attr('class', 'tooltip')
                .style('opacity', 0);

            var svg = d3.select('#tree').append('svg')
                .attr('width', width + margin.left + margin.right)
                .append('g')
                .attr('transform', `translate(${ margin.left },${ margin.top })`);

            function lineData(d) {
                var points = [{
                    x: d.source.y,
                    y: d.source.x
                }, {
                    x: d.target.y,
                    y: d.target.x
                }];

                return line(points);
            }

            root = treeData;
            root.x0 = 0;
            root.y0 = 0;

            update(root);

            function update(source) {
                // Compute the flattened node list.
                var nodes = tree.nodes(root);
                console.log(nodes);

                var height = Math.max(500, nodes.length * barHeight + margin.top + margin.bottom);

                d3.select('svg').transition()
                    .duration(duration)
                    .attr('height', height);

                d3.select(window.frameElement).transition()
                    .duration(duration)
                    .style('height', `${ height }px`);

                // Compute the layout.
                nodes.forEach(function(n, i) {
                    n.x = i * barHeight;
                });

                // Update the nodes.
                var node = svg.selectAll('g.node')
                    .data(nodes, function(d) {
                        return d.id || (d.id = ++i);
                    });

第二个是在 D3 V4 中,可以清楚地看出数组顺序非常不正确。许多对象从它们应该在的位置向上移动,因此它会导致奇怪的碰撞效果,如下所示: https://plnkr.co/edit/PGPw92URj24yDMrPenwE?p=preview

function _drawTree(treeData) {
            // This solves the maximum call stack issue with d3 layout function
            const margin = {
                    top: 55,
                    right: 20,
                    bottom: 30,
                    left: 30
                },
                width = 960 - margin.left - margin.right,
                barHeight = 65,
                barWidth = width * 0.35,
                duration = 400,
                treeMap = d3.tree()
                    .nodeSize([0, 75]);

            let i = 0,
                root;

            var line = d3.line()
                .x(d => d.x)
                .y(d => d.y - 12)
                .curve(d3.curveStep);

            // Define 'div' for tooltips
            var div = d3.select('#tree')
                // Declare the tooltip div
                .append('div')
                // Apply the 'tooltip' class
                .attr('class', 'tooltip')
                .style('opacity', 0);

            var svg = d3.select('#tree').append('svg')
                .attr('width', width + margin.left + margin.right)
                .append('g')
                .attr('transform', 'translate(' + margin.left + ',' + margin.top + ')');

             function lineData(d) {
                var points = [{
                    x: d.source.y,
                    y: d.source.x
                }, {
                    x: d.target.y,
                    y: d.target.x
                }];

                return line(points);
            }

            root = d3.hierarchy(treeData, d => {
                return d.subsidiaries;
                });
            root.x0 = 0;
            root.y0 = 0;

            update(root);

            function update(source) {
                var tree = treeMap(root);

                var nodes = tree.descendants(root);

                console.log(nodes);

                // Compute the flattened node list.
                var height = Math.max(500, nodes.length * barHeight + margin.top + margin.bottom);

                d3.select('svg').transition()
                    .duration(duration)
                    .attr('height', height);

                d3.select(window.frameElement).transition()
                    .duration(duration)
                    .style('height', height + 'px');

                // Compute the layout.
                nodes.forEach((n, i) => {
                    n.x = i * barHeight;
                });

我已经记录了必要的变量,你可以通过打开你的开发控制台来查看它们。

我不确定这些信息是否足够,如果您需要更多信息,请告诉我!感谢您的帮助!!!

【问题讨论】:

    标签: javascript angularjs d3.js tree


    【解决方案1】:

    原来答案其实比较简单。在布置节点时,我使用了 forEach 而不是 eachBefore。关于这个GitHub Issue的解决方案。

    他们链接到这个example,正确的解决方法是:

    // Compute the "layout". TODO https://github.com/d3/d3-hierarchy/issues/67
    var index = -1;
    root.eachBefore(function(n) {
        n.x = ++index * barHeight;
        n.y = n.depth * 20;
    });
    

    我还用正确的代码更新了我的 Plunker...

    【讨论】:

      猜你喜欢
      • 2020-10-11
      • 2018-10-07
      • 1970-01-01
      • 1970-01-01
      • 2012-06-18
      • 2021-06-16
      • 1970-01-01
      • 1970-01-01
      • 2019-07-31
      相关资源
      最近更新 更多