Javascript d3.js:是否将匿名函数作为参数传递给定心力?

Javascript d3.js:是否将匿名函数作为参数传递给定心力?,javascript,d3.js,svg,d3-force-directed,Javascript,D3.js,Svg,D3 Force Directed,我正在制作一个交互式气泡图,我正在开发将数据分成两组的功能,这两组数据将移动到屏幕的两侧。我在模拟中使用了一个对中力,因为我认为它比使用forceX和forceY提供了更好、更一致的数据显示。但是,我在分割数据时遇到了问题 我的想法是,由于可以将匿名函数作为参数传递给forceX,以确定节点是向左移动还是向右移动,因此理论上可以对定心力中的x值执行相同的操作。我的中心力代码如下所示: var forceCenterSplit = d3.forceCenter(function(d) {

我正在制作一个交互式气泡图,我正在开发将数据分成两组的功能,这两组数据将移动到屏幕的两侧。我在模拟中使用了一个对中力,因为我认为它比使用forceX和forceY提供了更好、更一致的数据显示。但是,我在分割数据时遇到了问题

我的想法是,由于可以将匿名函数作为参数传递给forceX,以确定节点是向左移动还是向右移动,因此理论上可以对定心力中的x值执行相同的操作。我的中心力代码如下所示:

var forceCenterSplit = d3.forceCenter(function(d) {
            if (d[splitParameter] >= splitVal)
                return 3*width/4;
            else
                return width/4;
        }, height/2)
为了进行比较,下面是forceX的代码,它实现了相同的功能:

var forceXsplit = d3.forceX(function(d) {
                if (d[splitParameter] >= splitVal)
                    return 3*width/4;
                else
                    return width/4;
            }).strength(.05);    
不幸的是,当我运行定心力并将所有数据推送到cx=0(默认值)时,控制台会说“意外值”

我是不是错过了一些基本的东西?不能将匿名函数作为参数传递给定心力吗?如果没有,有没有更好的方法

谢谢


不幸的是,答案似乎是否定的

由于d3.forceCenter的本质,不可能(“将匿名函数作为参数传递”)。API说:

定心力均匀地平移节点,以便所有节点的平均位置(如果所有节点重量相等,则为质心)位于给定位置⟨x、 y⟩. (强调矿山)

因此,这里没有用于访问器函数的空间<代码>强制力和
强制力
,另一方面

将坐标访问器设置为指定的数字或函数。(再次强调我的)


。。。而且可能最适合您。

就d3.forceCenter的本质而言,这是不可能的。API说:“定心力均匀地平移节点,使所有节点的平均位置(如果所有节点的重量相等,则为质心)位于给定位置⟨x、 y⟩.", emphasis mine。因此,此处没有用于访问器函数的空间。
forceX
forceY
,另一方面,“将坐标访问器设置为指定的数字或函数”(再次强调mine)但是,如果你有两个模拟,你会如何使用
碰撞
来避免重叠的节点?除非节点彼此非常分离。如果看不到实际的代码,很难说什么,但是你可以增加
碰撞
的半径并更改
速度缓存
。我建议你发布另一个问题.现在,这个问题有一个明确的答案,那就是“不”“。如果你发布另一个关于forceX和forceY使用的问题,并附上具体细节,你会得到更多的关注。同时,我将复制/粘贴我的第一条评论作为答案。@PaulMurray这看起来有点像我几天前发布答案的问题:。如果不是你问题的答案,它可能会提供一些有趣的想法。
// nicer looking splitting forces that use forceCenter
        var forceCenterCombine = d3.forceCenter(width/2, height/2);

        var forceCenterSplit = d3.forceCenter(function(d) {
            if (d[splitParameter] >= splitVal)
                return 3*width/4;
            else
                return width/4;
        }, height/2);

        // simple splitting forces that only use forceX
        var forceXSplit = d3.forceX(function(d) {
            if (d[splitParameter] >= splitVal)
                return 3*width/4;
            else
                return width/4;
        }).strength(.05);

        var forceXCombine = d3.forceX(width/2).strength(.05);

        // collision force to stop the bubbles from hitting each other
        var forceCollide = d3.forceCollide(function(d){
            console.log("forceCollide");
            return radiusScale(d[radiusParam]) + 1;
        }).strength(.75)

        // This code is for the simulation that combines all the forces
        var simulation = d3.forceSimulation()
            .force("center", forceCenterCombine)
            .force("collide", forceCollide)
            .on('end', function(){console.log("Simulation ended!");});

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

var splitFlag = false;

        // dynamically divide the bubbles into two (or probably more later on) groups
        $scope.split = function() {
            // split them apart
            if (!splitFlag){
                console.log("splitForce");
                simulation.force("center", forceXSplit)
                    .force("y", d3.forceY(height/2).strength(.05))
                    .alphaTarget(.25)
                    .restart();
                splitFlag = true;
            }
            // bring them back together
            else {
                console.log("combineForce");
                simulation.force("center", forceCenterCombine)
                    .alphaTarget(.25)
                    .restart();
                splitFlag = false;
            }
        };