D3力导向图添加新节点会导致x& y为NaN [英] D3 force-directed graph adding new nodes causes x & y to be NaN

查看:110
本文介绍了D3力导向图添加新节点会导致x& y为NaN的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我单击一个节点时,我希望向其添加一个新节点.它们都应该有标签(我正在尝试建立同义词库可视化文件.)

When I click on a node, I want a new node to be added to it. They should both have labels (I'm trying to build a thesaurus visualization).

我是D3的新手,如果您需要更详细地说明事情,我深表歉意.

I'm very new to D3, so I apologize if you have to explain things in a bit more detail.

到目前为止,这是我的代码:

This is my code so far:

var width = 960;
var height = 500;

var force = d3.layout.force()
    .gravity(0.05)
    .distance(100)
    .charge(-100)
    .size([width, height])
    .nodes([{ "name": "One", "group": 1 }])
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var nodes = force.nodes();
var links = force.links();

var link = svg.selectAll(".link")
    .data(links)
    .enter().append("line")
    .attr("class", "link");

var node = svg.selectAll(".node")
    .data(force.nodes())
    .enter().append("g")
    .attr("class", "node")
    .call(force.drag);

node.append("circle")
    .attr("r", 10)
    .on("mousedown", onClick);

node.append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text(d => d.name);

force.on("tick", function() {
    link.attr("x1", d => d.source.x)
        .attr("y1", d => d.source.y)
        .attr("x2", d => d.target.x)
        .attr("y2", d => d.target.y);

    node.attr("transform", d => {
        // d.x & d.y are NaN for new nodes
        return "translate(" + d.x + "," + d.y + ")";
    });
});

restart();

function restart() {
    node = node.data(nodes);

    node.enter().append("g")
        .attr("class", "node")
        .call(force.drag);
    node.append("circle")
        .attr("r", 10)
        .on("mousedown", onClick);
    node.append("text")
        .attr("dx", 12)
        .attr("dy", ".35em")
        .text(d => d.name);
    node.exit().remove();

    link = link.data(links);
}

function onClick(clicked_node) {
    console.log("click!");
    console.log(clicked_node);
    var new_node = { name: "Test", group: 2 };
    nodes.push(new_node);
    // Has x & y set to NaN after adding
    links.push({ source: clicked_node, target: new_node });
    restart();
}

当我单击第一个节点时,导致该节点

As soon as I click on the first node, causing the node

{ name: "Test", group: 2 };

要添加的内容,D3会引发错误

to be added, D3 throws errors within

node.attr("transform", d => {
    // d.x & d.y are NaN for new nodes
    return "translate(" + d.x + "," + d.y + ")";
});

因为此新节点的d.xd.yNaN.

我尝试明确设置它们:

{ name: "Test", group: 2, x: clicked_node.y, y: clicked_node.y };

但是我得到了同样的错误.在检查器中,将此节点添加到屏幕后,xy值将改为pxpy值!

But I get the same error. In the inspector, when this node is added to the screen, the x and y values becomes the px and py values instead!

我不明白为什么会这样.

I don't understand why this happens.

推荐答案

您缺少一行代码.添加新节点后,需要重新启动d3的仿真以计算其位置:

You are missing one line of code. After you add your new node you need to restart the simulation for d3 to calculate it's position:

function restart() {
    node = node.data(nodes);

    node.enter().append("g")
        .attr("class", "node")
        .call(force.drag);
    node.append("circle")
        .attr("r", 10)
        .on("mousedown", onClick);
    node.append("text")
        .attr("dx", 12)
        .attr("dy", ".35em")
        .text(d => d.name);
    node.exit().remove();

    link = link.data(links);

    force.start(); //<-- start simulation
}

运行代码:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="d3@3.5.17" data-semver="3.5.17" src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.17/d3.js"></script>
  </head>

  <body>
    <script>
      var width = 960;
var height = 500;

var force = d3.layout.force()
    .gravity(0.05)
    .distance(100)
    .charge(-100)
    .size([width, height])
    .nodes([{ "name": "One", "group": 1 }])
    .start();

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

var nodes = force.nodes();
var links = force.links();

var link = svg.selectAll(".link")
    .data(links)
    .enter().append("line")
    .attr("class", "link");

var node = svg.selectAll(".node")
    .data(force.nodes())
    .enter().append("g")
    .attr("class", "node")
    .call(force.drag);

node.append("circle")
    .attr("r", 10)
    .on("mousedown", onClick);

node.append("text")
    .attr("dx", 12)
    .attr("dy", ".35em")
    .text(d => d.name);

force.on("tick", function() {
    link.attr("x1", d => d.source.x)
        .attr("y1", d => d.source.y)
        .attr("x2", d => d.target.x)
        .attr("y2", d => d.target.y);

    node.attr("transform", d => {
        // d.x & d.y are NaN for new nodes
        return "translate(" + d.x + "," + d.y + ")";
    });
});

restart();

function restart() {
    node = node.data(nodes);

    node.enter().append("g")
        .attr("class", "node")
        .call(force.drag);
    node.append("circle")
        .attr("r", 10)
        .on("mousedown", onClick);
    node.append("text")
        .attr("dx", 12)
        .attr("dy", ".35em")
        .text(d => d.name);
    node.exit().remove();

    link = link.data(links);
    
    force.start();
}

function onClick(clicked_node) {
    console.log("click!");
    console.log(clicked_node);
    var new_node = { name: "Test", group: 2 };
    nodes.push(new_node);
    // Has x & y set to NaN after adding
    links.push({ source: clicked_node, target: new_node });
    restart();
}
    </script>
  </body>

</html>

这篇关于D3力导向图添加新节点会导致x&amp; y为NaN的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆