2016-08-17 3 views
3

В D3 v4 с силовым модулем, как вы обновляете параметры моделирования после инициализации графика?Параметры обновления D3-Force после инициализации графика

Точнее, я пытаюсь изменить .forceLink и .forceManyBody диаграммы направленности усилия, когда пользователь щелкает один из своих узлов.

var node = svg 
    .append("g") 
    .attr("class", "gnodes") 
    .selectAll(".node") 
    .data(graph.nodes) 
    .enter() 
    .append("g") 
    .attr("class", "node") 
    .on('dblclick', connectedNodes); //calls for change in simulation parameters 

До сих пор я был в состоянии обновить его путем дублирования имитации под функцией connectedNodes:

function connectedNodes() { 

//new parameters 
linkDistance = 5; 
fCharge = -10; 

//replicates the initial simulation code 
simulation = d3.forceSimulation() 
    .force("link", d3.forceLink() 
     .id(function(d) {return d.id;}) 
     .distance(linkDistance) 
     ) 
    .force("collide", d3.forceCollide() 
     .radius(function(d){return d.r + 10}) 
     .strength(1) 
     ) 
    .force("charge", d3.forceManyBody() 
     .strength(fCharge) 
     ) 
    .force("center", d3.forceCenter(width/2, height/2)); 

simulation.nodes(graph.nodes).on("tick", ticked); 

simulation.force("link").links(graph.links); 

Хотя это работает очень избыточно. Есть ли способ, в котором симуляция может быть обновлена ​​с помощью новых параметров? Я пробовал следующее, но он не работает

function connectedNodes() { 

//new parameters 
linkDistance = 5; 
fCharge = -10; 

//restart simulation with new parameters 
simulation.restart(); 
} 
+0

Любому, кто заинтересован в этом, должен увидеть эту удивительную демонстрационную версию, которая выполняет ее для всех переменных силы графика: https://bl.ocks.org/steveharoz/8c3e2524079a8c440df60c1ab72b5d03 –

ответ

5

Вам нужна ссылка на силы, которые вы хотели бы обновить. Это может быть сделано с помощью одного из двух способов:

  1. Как было отмечено Cool Blue в их comment, вы можете легко получить ссылку на силу, вызвав simulation.force() передавая только имя силы оно было зарегистрировано с в первую очередь. Если бы мы имели, якобы, создали наше моделирование при прохождении в анонимной, в месте силы, как так:

    var simulation = d3.forceSimulation() 
        .force("link", d3.forceLink()   // "link" is the name to register the force 
        .id(function(d) { return d.id; }) 
        .distance(linkDistance) 
    ); 
    

    Позже силы можно получить по его имени, когда это необходимо:

    var forceLink = simulation.force("link"); // Get the force by its name 
    

    Лично , Мне нравится этот подход и предпочтет его по второму, когда это возможно, потому что мне не нравится иметь много ссылок/переменных.

  2. Держите ссылку на силу при ее создании.

    var forceLink = d3.forceLink()  // Keep a reference to the force 
        .id(function(d) { return d.id; }) 
        .distance(linkDistance); 
    
    var simulation = d3.forceSimulation() 
        .force("link", forceLink)  // Pass the reference when creating the simulation 
    

Независимо от того, какой путь вы выбрали, вы можете затем обновить вашу силу, делая что-то вроде

linkDistance += 10; 
forceLink.distance(linkDistance); 

Это займет новое значение во внимание после того, как следующий тик рассчитывается. Если моделирование уже пришло к остановке или вы просто хотите, чтобы нагреть его снова можно назвать

simulation.alpha(1).restart(); 

Я создал example, который показывает эти живые обновления при наведении курсора мыши на SVG. Это обновит linkDistance и перезапустит компоновку сил.

+0

У меня возникли проблемы с обновлением функции forcecollide. Граф сначала инициализируется, а затем изменяется, когда пользователь нажимает. Во время этого изменения размер некоторых узлов изменен. Симуляторы силы отзываются после вашего предложения. Все силы работают, за исключением forceCollide, который не обновляется, чтобы учитывать новый радиус. Я редактирую вопрос, чтобы включить некоторый код. –

+1

@ PepeG-a Это вопрос сам по себе. Пожалуйста, не редактируйте это в своем вопросе, так как это только путает читателей.Скорее опубликуйте новую и верните ссылку на нее. Я собираюсь изучить его, как только вы разместили его. – altocumulus

+0

, конечно, будет делать @altocumulus –