在D3力导向图中,“固定”节点

4

我构建了一个常规的“网格”,在整个网格中均匀放置节点。然后,通过随机化链接距离,我能够“搅动”网格,使其不那么规则。

我想“固定”所有边缘点,使它们不动 - 只留下内部点受到力布局的影响。

我的想法是,由于这是一个常规的四分网格,任何权重小于4的点都是“边缘”点,因此应该被固定。

我认为权重只有在将节点和链接添加到力布局之后才会计算,因此我在将其添加到力布局后遍历节点数组,并根据权重有条件地设置fixed属性。

然后,我重新应用节点属性并启动模拟。

但效果不好。在我附加的示例中,所有点都移动了。

force = d3.layout.force()
                .size( [w, h ] )
                .nodes( nodes )
                .links( links )
                .linkDistance( function( d ){ return Math.random() * GRID_SPACING; } )
                .linkStrength( 1 )
                .charge( 0 )
                .gravity( 0 )
                .friction( .5 )
                .on( "tick", function() {
                    d3links.attr("x1", function(d) { return d.source.x; })
                        .attr("y1", function(d) { return d.source.y; })
                        .attr("x2", function(d) { return d.target.x; })
                        .attr("y2", function(d) { return d.target.y; });

                    d3nodes.attr("cx", function(d) { return d.x; })
                        .attr("cy", function(d) { return d.y; });
                } );

            // "Pin" all the edge nodes.
            nodes.forEach( function( node ){
                if ( node.weight < 4 ){
                    node.fixed = true;
                }
            } );

            force.nodes( nodes ).start();
1个回答

2
你的想法很不错!但是时间非常重要...
“start”事件在权重初始化后触发,所以这应该可以正常工作...
force = d3.layout.force()
    .size([w, h])
    .nodes(nodes)
    .links(links)
    .linkDistance(function (d) { return Math.random() * GRID_SPACING; })
    .linkStrength(1)
    .charge(0)
    .gravity(0)
    .friction(.5)
    .on("tick", function () {
        d3links.attr("x1", function (d) { return d.source.x; })
                .attr("y1", function (d) { return d.source.y; })
                .attr("x2", function (d) { return d.target.x; })
                .attr("y2", function (d) { return d.target.y; });

        d3nodes.attr("cx", function (d) { return d.x; })
                .attr("cy", function (d) { return d.y; });
    })
    .on("start", function () {
        // "Pin" all the edge nodes.
        nodes.forEach(function (node) {
            if (node.weight < 4) {
                node.fixed = true;
            }
        });
    })


force.nodes(nodes).start();

(如果你想包含拖拽行为,那么你需要在拖拽结束后重新修复。)

搞定了!所以我猜测直到力布局实际启动后才计算权重。在我的代码中,我没有启动布局,因此权重都是未定义的,因此没有一个节点符合我的“固定”标准。奇怪的是它没有抛出错误。 - Tom Auger
不需要猜测@TomAuger,只需阅读d3代码,在该模块中非常直观。;) - Cool Blue

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接