Я делаю интерактивную диаграмму пузырьков, и я работаю над функциональностью, чтобы разделить данные на две группы, которые перемещаются на противоположные стороны экрана. Я использую центрирующую силу для моделирования, потому что я думаю, что это дает гораздо более приятное и более последовательное отображение данных, чем использование forceX и forceY. Однако у меня возникают проблемы с разбиением моих данных.d3.js: передать анонимную функцию в качестве параметра для центрирования?
У меня возникла мысль, что, поскольку вы можете передать анонимную функцию в качестве параметра 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 = 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⟩. * * акцент мой. Таким образом, здесь нет места для функции доступа. 'forceX' и' forceY', с другой стороны, * "установите аксессуар координат на указанное число или ** функцию **" * (снова ударьте мое внимание). –
А, это раздражает.Как я уже упоминал в исходном сообщении, forceX и forceY дают намного более четкое отображение, чем forceCenter - узлы, сталкивающиеся бесконечно, застревают в кластерах других узлов, не перемещаются так далеко, как они предполагают, и т. Д. Я предполагаю единственный способ, которым я мог бы иметь два разных центра масс, - это иметь разные симуляции, работающие на двух разных наборах узлов? Спасибо за ответ кстати –
Но если у вас есть 2 моделирования, как бы вы использовали 'collide', чтобы избежать перекрытия узлов? Если узлы не разделены друг от друга. –