私はインタラクティブなバブルチャートを作成しています。私は、画面の反対側に移動する2つのグループにデータを分割する機能について取り組んでいます。私はシミュレーションのためにセンタリング力を使用しています。なぜなら、それはforceXとforceYを使用するよりもずっと素敵でより一貫性のあるデータ表示を与えると思うからです。しかし、データの分割に問題があります。d3.js:パラメータとして匿名関数をセンタリング力に渡しますか?
匿名関数をforceXに渡してノードが左右に動くかどうかを判断することができるので、理論的には同じことを芯出しの力で行うことができます。マイ中央力コードは次のようになります、コンソールが予期しない値NaNでCXを解析する」と言っている残念ながら
var forceXsplit = d3.forceX(function(d) {
if (d[splitParameter] >= splitVal)
return 3*width/4;
else
return width/4;
}).strength(.05);
:
比較のためにvar forceCenterSplit = d3.forceCenter(function(d) {
if (d[splitParameter] >= splitVal)
return 3*width/4;
else
return width/4;
}, height/2)
、ここで同じことを実現FORCEXためのコードがあります属性。"センタリングを実行して、すべてのデータを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;
}
};
「d3.forceCenter」の性質上、これは不可能です。 APIは次のように述べています:「センタリング力はノードを均等に変換して、すべてのノードの平均位置**(すべてのノードが等しい重みを持つ場合の質量の中心)が与えられた位置⟨x、y⟩にある」*私の強調。したがって、アクセサー関数のためのスペースはここにありません。一方、「アクセサーを指定された数に設定するか、** function **」*(強調するもう一度)を実行します。 –
ああ、それは迷惑だ。私が元の記事で述べたように、forceXとforceYはforceCenterよりもはるかに細かい表示をしています - ノードは無限に衝突し、他のノードのクラスタに詰まったり、移動したりしません。 2つの異なる質量中心を持つことができる唯一の方法は、2つの異なるノードセットで異なるシミュレーションを実行することです。 返信ありがとうございました –
しかし、2つのシミュレーションがある場合、重複ノードを避けるために 'collide'をどのように使いますか?ノードが非常に離れている場合を除きます。 –