D3 V3到D3 V4树阵列使用层次结构重新排序错误 [英] D3 V3 to D3 V4 Tree Array Reordered Wrong Using Hierarchy

查看:178
本文介绍了D3 V3到D3 V4树阵列使用层次结构重新排序错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这可能听起来比我想要的更复杂,但是,我正在从D3 V3切换到D3 V4。我的所有其他图形和图表都很容易转移,但是这个特定的图表(一棵树)引起各种各样的悲痛,从d3.layout.tree改变,只需使用.children()函数然后设置节点/链接使用d3.hierarchy()的新方法。我把它设置为我在无数教程中看到的方式。



我设置了2个不同的Plunkers。
这个是在D3 V3中,正在使用正确的数组顺序正常工作/显示:

  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 dx;
})
.y(函数(d){
返回dy - 12;
});

//为工具提示定义'div'
var div = d3.select('#tree')
//声明工具提示div
.append(' div')
//应用'tooltip'类
.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
}];

返回线(点数);
}

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

update(root);

函数更新(源){
//计算展平节点列表。
var nodes = tree.nodes(root);
console.log(节点);

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`);

//计算布局。
nodes.forEach(function(n,i){
n.x = i * barHeight;
});

//更新节点。
var node = svg.selectAll('g.node')
.data(nodes,function(d){
return d.id ||(d.id = ++ i) ;
});

第二个是在D3 V4中,很明显告诉数组顺序非常不正确。许多对象从它们应该的位置向上移动到列表中,因此它会导致奇怪的碰撞效果,如下所示:



< img src =https://i.stack.imgur.com/Aup0b.pngalt =不同的数据结构和对象顺序>

  function _drawTree(treeData){
//这解决了d3布局函数的最大调用堆栈问题
const margin = {
top:55,
右:20,
底部:30,
剩余:30
},
width = 960 - margin.left - margin.right,
barHeight = 65,
barWidth = width * 0.35,
duration = 400,
treeMap = d3.tree()
.nodeSize([0,75]);

让i = 0,
root;

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

//为工具提示定义'div'
var div = d3.select('#tree')
//声明工具提示div
.append(' div')
//应用'tooltip'类
.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
}];

返回线(点数);
}

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

update(root);

函数更新(源){
var tree = treeMap(root);

var nodes = tree.descendants(root);

console.log(节点);

//计算展平节点列表。
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');

//计算布局。
nodes.forEach((n,i)=> {
n.x = i * barHeight;
});

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

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

解决方案

事实证明答案实际上相对简单。在布置节点时,我使用forEach而不是eachBefore。关于 GitHub问题的解决方案。



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

  //计算布局。 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 ...


This may sound more complex than I intend it to, however, I am switching from D3 V3 to D3 V4. ALL of my other graphs and charts have transferred over really easily, but this specific one (a tree) is causing all sorts of grief from changing from d3.layout.tree and simply using the .children() function then setting nodes/links the old way to the new way using d3.hierarchy(). I set it the way that I've seen in countless tutorials.

I have 2 different Plunkers set up. This one is in D3 V3 and is working/displaying properly with the correct array order: 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);
                    });

This second one is in D3 V4, and it's clear to tell that the array order is extremely incorrect. Many of the objects are moved up the list from where they are supposed to be, so it's causing a weird collided effect as seen here: 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;
                });

I've logged the necessary variables, and you can view them by popping open your dev console.

I'm not sure if this is enough information or not, please let me know if you need more! Thanks for the help!!!

解决方案

It turns out that the answer was actually relatively simple. I was using forEach instead of eachBefore when laying out the nodes. The solution on this GitHub Issue.

They link to this example, and the correct fix is this:

// 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;
});

I have also updated my Plunker with the correct code in action...

这篇关于D3 V3到D3 V4树阵列使用层次结构重新排序错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆