我正在制作一个交互式气泡图,并且正在研究将数据分成两组移动到屏幕两侧的功能。我在模拟中使用了定心力,因为我认为它比使用 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);
不幸的是,控制台说“Unexpected value NaN parsing cx attribute”。当我运行定心力并将所有数据推送到 cx = 0 (默认值)时。
我在这里缺少一些基本的东西吗?您不能将匿名函数作为参数传递给定心力吗?如果没有,有没有更好的方法来做到这一点?
谢谢!
// 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;
}
};