У меня есть силовой ориентированный граф, у которого есть узлы (круги) в разных кластерах и движение круга из одного места в другое.Это то, что я копирую https://flowingdata.com/2016/08/23/make-a-moving-bubbles-chart-to-show-clustering-and-distributions/ Что я хочу сделать, это контролировать движение пузырьков при их перемещении из одного кластера в другой
Мой первоначальный подход состоял в том, чтобы поместить переход в тиковый методОднако в соответствии с полученным предложением и после того, как я еще больше подумал, я чувствую, что не стоит помещать переход в тик, как он называется несколько раз.Однако движение пузырьков контролируется внутри функции тика, которая, в свою очередь, вызывает функцию гравитации.Мой вопрос - возможно ли в этом сценарии управлять движением пузырьков?
Не могли бы вы сообщить мне, подходит ли выбранный мной подход именно здесь?Если да, что я делаю не так в текущем коде?Если нет, подскажите, пожалуйста, в каком направлении мне нужно двигаться?
Обновление:
Я удалил код из функции тиков согласно комментариям и включил его в функцию таймерачто я использую для анимации и код выглядит следующим образом
var force = d3.forceSimulation(nodes)
.force('charge', d3.forceManyBody().strength(-300))
.force('collision', d3.forceCollide().radius(function (d) {
return 1.1 * d.radius;
}))
.on('tick', tick);
force.alpha(0.01);
force.alphaDecay = 0.1;
force.alphaTarget(.001);
force.force('x', d3.forceX().x(function (d) {
return foci[d.state].x;
}));
force.force('y', d3.forceY().y(function (d) {
return foci[d.state].y;
}));
function tick(e) {
circle
.each(gravity(.051 * .8))
.style("fill", function (d) {
return d.color;
})
.attr("cx", function (d) {
return d.x;
})
.attr("cy", function (d) {
return d.y;
})
}
setTimeout(timer, 10);
function timer() {
var freezeTimer = 1000;
d3.range(nodes.length).map(function (i) {
var currentNode = nodes[i];
// some business logic to update node object
console.log(d3.select("#circle_" +currentNode.id));
d3.select("#circle_" +currentNode.id)
.transition()
.attrTween("pathTween", function(d) {
// console.log(this);
if(d.previousState == 0 && d.state == 4) {
var lineData1 = [
{ x: 840, y: 600 },
{ x: 800, y: 220 },
{ x: 120, y: 120 },
];
var path = svg.append("path")
.attr("d", line(lineData1))
.attr("stroke", "red")
.attr("fill", "none")
.attr("stroke-width", 1)
.attr("stroke-linecap", "round")
.attr("opacity", "0.5");
var length = path.node().getTotalLength(); // Get the length of the path
// console.log("Length: " + length);
var r = d3.interpolate(0, length); //Set up interpolation from 0 to the path length
return function(t){
var point = path.node().getPointAtLength(r(t)); // Get the next point along the path
// console.log(point);
circle // Select the circle
.attr("x", point.x) // Set the cx
.attr("y", point.y)
.attr("r", 4) // Set the cy
}
}
});
});