d3.js:将匿名函数作为参数传递给中心力? [英] d3.js: Pass anonymous function as parameter to centering force?

查看:337
本文介绍了d3.js:将匿名函数作为参数传递给中心力?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在制作交互式气泡图,我正在开发功能将数据分成两组,移动到屏幕的相对两侧。我使用一个中心力我的模拟,因为我认为它提供了一个更好更一致的数据显示比使用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);不幸的是,控制台正在说意外值NaN解析cx属性。当我运行中心力,并推动所有的数据到cx = 0(默认值)。



我缺少一些基本的吗?你不能将匿名函数作为参数传递给中心力吗?如果没有,是否有更好的方法这样做?



谢谢!





  //更好的分割力使用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);

//简单拆分力只能使用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);

//碰撞力阻止气泡相互碰撞
var forceCollide = d3.forceCollide(function(d){
console.log(forceCollide);
return radiusScale(d [radiusParam])+ 1;
})。strength(.75)

//此代码用于模拟, b var simulation = d3.forceSimulation()
.force(center,forceCenterCombine)
.force(collide,forceCollide)
.on console.log(Simulation ended!);});

function ticked(){
circles
.attr(cx,function(d){
return dx;
})
.attr(cy,function(d){
return dy;
})
}

var splitFlag = false;

//动态地将气泡划分为两个(或可能更多)组
$ scope.split = function(){
//将它们分开
if(!splitFlag){
console.log(splitForce);
simulation.force(center,forceXSplit)
.force(y,d3.forceY(height / 2).strength(.05))
.alphaTarget
.restart();
splitFlag = true;
}
//将它们集中在一起
else {
console.log(combineForce);
simulation.force(center,forceCenterCombine)
.alphaTarget(.25)
.restart();
splitFlag = false;
}
};



由于非常性质的 d3.forceCenter ,(将匿名函数作为参数)是不可能的。 API说:


中心力均匀地平移节点,使所有节点如果所有节点具有相等的权重)在给定位置⟨x,y⟩。 (强调我的)


因此,这里没有空格用于存取函数。 forceX forceY ,另一方面...



< blockquote>

将坐标存取程序设置为指定的数字或函数。 (再次强调我)


...并且最适合你。


I'm making an interactive bubble chart and I'm working on functionality to split the data into two groups which move to opposite sides of the screen. I'm using a centering force for my simulation because I think it gives a much nicer and more consistent display of the data than using forceX and forceY does. However, I'm having trouble with the splitting of my data.

I had the idea that, since you can pass an anonymous function as a parameter to forceX to determine whether a node moves left or right, you could theoretically do the same thing for the x value in a centering force. My center force code looks like this:

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

For comparison, here is the code for the forceX that accomplishes the same thing:

var forceXsplit = d3.forceX(function(d) {
                if (d[splitParameter] >= splitVal)
                    return 3*width/4;
                else
                    return width/4;
            }).strength(.05);    

Unfortunately, the console is saying "Unexpected value NaN parsing cx attribute." when I run the centering force and is pushing all of the data to cx = 0 (the default value).

Am I missing something basic here? Can you not pass an anonymous function as a parameter to the centering force? If not, is there a better way to do this?

Thanks!

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

解决方案

Unfortunately, the answer seems to be no.

Due to the very nature of d3.forceCenter, that ("pass an anonymous function as a parameter") is not possible. The API says:

The centering force translates nodes uniformly so that the mean position of all nodes (the center of mass if all nodes have equal weight) is at the given position ⟨x,y⟩. (emphasis mine)

Thus, there is no space for an accessor function here. forceX and forceY, on the other hand...

set the coordinate accessor to the specified number or function. (emphasis mine again)

... and may suit you best.

这篇关于d3.js:将匿名函数作为参数传递给中心力?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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