I am making an interactive bubble chart, and I am working on functionality to divide the data into two groups that move to opposite sides of the screen. I use centering force for modeling, because I think it gives a much nicer and more consistent display of data than using forceX and forceY. However, I am having problems splitting my data.
I had the idea that since you can pass an anonymous function as a forceX parameter to determine if the node moves left or right, theoretically you can do the same for the value of x in the centering force. My central power 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 forceX that does 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 says "Unexpected NaN value for parsing the cx attribute." when I start the centering force and push all the data to cx = 0 (default value).
Did I miss something basic here? Can you pass an anonymous function as a parameter of the centering force? If not, is there a better way to do this?
Thank!


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);
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)
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;
$scope.split = function() {
if (!splitFlag){
console.log("splitForce");
simulation.force("center", forceXSplit)
.force("y", d3.forceY(height/2).strength(.05))
.alphaTarget(.25)
.restart();
splitFlag = true;
}
else {
console.log("combineForce");
simulation.force("center", forceCenterCombine)
.alphaTarget(.25)
.restart();
splitFlag = false;
}
};
