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