D3-初始化图形后强制更新参数

时间:2016-08-17 11:49:16

标签: d3.js force-layout

在带有强制模块的D3 v4中,初始化图形后如何更新模拟参数?

更确切地说,当用户点击其中一个节点时,我正在尝试更改力导向图的 <?php session_start(); try { //$con= new PDO('mysql:host=localhost;dbname=wydania_tonery', "sa", "sql"); $zmien_kodowanie = $dbo->query("SET names 'utf8'"); $sesja = $_SESSION['username']; $query = "SELECT mdl_user.firstname AS 'Imie', mdl_user.lastname AS 'Nazwisko', mdl_user.department AS 'Akronim', reg.data AS 'Region', sta.data AS 'Stanowisko', mdl_user.aim AS 'Stan', NULLIF('Uwagi', 0) AS 'Uwagi' FROM mdl_user LEFT JOIN mdl_user_info_data AS reg ON reg.userid=mdl_user.id AND reg.fieldid='2' LEFT JOIN mdl_user_info_data AS sta ON sta.userid=mdl_user.id AND sta.fieldid='4' WHERE mdl_user.email LIKE 'kierownik.%' AND mdl_user.deleted='0' AND mdl_user_info_data.fieldid = ".$_SESSION['username']." /*AND mdl_user.department='BBT'*/ ORDER BY mdl_user.department ASC"; //first pass just gets the column name echo "<table> \n"; $result = $dbo->query($query); //return only the first row (we only need field names) $row = $result->fetch(PDO::FETCH_ASSOC); print " <tr> \n"; foreach ($row as $field => $value){ print " <th>$field</th> \n"; } // end foreach print " </tr> \n"; //second query gets the data $data = $dbo->query($query); $data->setFetchMode(PDO::FETCH_ASSOC); foreach($data as $row){ print " <tr> \n"; foreach ($row as $name=>$value){ print " <td>$value</td> \n"; } // end field loop print " </tr> \n"; } // end record loop print "</table> \n"; } catch(PDOException $e) { echo 'ERROR: ' . $e->getMessage(); } // end try ?> .forceLink

.forceManyBody

到目前为止,我已经能够通过在connectedNodes函数下复制模拟来更新它:

 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

虽然这有效,但它非常多余。有没有一种方法可以使用新参数刷新模拟?我尝试了以下但它不起作用

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);

1 个答案:

答案 0 :(得分: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
    
  3. 无论您选择哪种方式,您都可以通过执行类似

    的操作来更新您的力量
    linkDistance += 10;
    forceLink.distance(linkDistance);
    

    一旦计算下一个滴答,这将考虑新值。如果模拟已经停止,或者您只是想再次加热,可以致电

    simulation.alpha(1).restart();
    

    我已设置example,当您将鼠标悬停在SVG上时会显示这些实时更新。这将更新linkDistance并重新启动力布局。