【问题标题】:Why does d3 say some nodes are missing after applying link force?为什么 d3 在应用链接力后会说某些节点丢失?
【发布时间】:2017-10-19 03:42:19
【问题描述】:

我正在尝试阅读一本名为“网络交互式数据可视化”的书。我想尝试建立那里描述的力图。当我使用这本书的虚拟数据时一切都很好,但是当我尝试自己的数据时,我不断收到错误消息,提示缺少节点 17。当我将此节点的目标更改为 16 时,它会说缺少 18。最终,当我将 16、17 和 18 全部更改为 15 时,图表将最终显示。但是显示的图表中仍然缺少一些节点的边缘。

我为数据尝试了所有不同的字符串/整数可能性,但没有成功。数据与来自数据库查询结果的 forEach 放在一起。源和目标整数是数据库中节点的 id。最后一个结果将因此有一个不必要的逗号,但这似乎也不重要。

当我保留节点的原始目标值并删除这行代码时:.force("link", d3.forceLink(graph.links)) 图形将显示没有边,节点将分散在整个 SVG 上。当我按源数据对数据进行排序时,控制台会说 d3 is not defined... 我真的迷失了这个。

我看过很多帖子,其中给出了未定义的值或空值作为原因,但我真的不明白如何相应地更改我的代码。在控制台中,可以清楚地看到一些节点在施加力后分配给它们的索引号,而有些则没有。但我只是不知道去哪里。请帮助我正确的方向。这就是我尝试将图形数据放在 Node.js 中的方式:

var graph = {
            nodes: [
                <% nodes.forEach(function(a){ %>
                    {category: "<%= a.properties.Name %>"},
                <% }); %>
            ],
            links: [
                <% edges.forEach(function(a){ %>
                    {"source": <%= a.source %>, "target": <%= a.target %>},
                <% }); %>
            ]
        }

这就是数据集中称为图的内容:

var graph = {
            nodes: [
           {Name: "b"},
           {Name: "c"},
           {Name: "c"},
           {Name: "c"},
           {Name: "b"},
           {Name: "b"},
           {Name: "c"},
           {Name: "c"},
           {Name: "c"},
           {Name: "b"},
           {Name: "c"},
           {Name: "c"},
           {Name: "d"},
           {Name: "d"},
           {Name: "a"},
           {Name: "c"}
        ],
        links: [
            {source: 8, target: 3},
            {source: 3, target: 5},
            {source: 3, target: 6},
            {source: 3, target: 7},
            {source: 3, target: 11},
            {source: 3, target: 12},
            {source: 8, target: 0},
            {source: 0, target: 13},
            {source: 0, target: 14},
            {source: 8, target: 9},
            {source: 9, target: 17},
            {source: 9, target: 18},
            {source: 14,target: 15},
            {source: 14,target: 16},
            {source: 8, target: 10}                  
            ]
        }

这是我从书中复制的 d3 代码:

var w = 800;
        var h = 400;

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

        var force = d3.forceSimulation(graph.nodes)
        .force("charge", d3.forceManyBody())
        .force("link", d3.forceLink(graph.edges))
        .force("center", d3.forceCenter().x(w/1).y(h/1))

        var edges = svg.selectAll("line")
            .data(graph.edges)
            .enter()
            .append("line")
            .style("stroke", "#ccc")
            .style("stroke-width", 1)


        var nodes = svg.selectAll("circle")
            .data(graph.nodes)
            .enter()
            .append("circle")
            .attr("r", 10)


            nodes.append("title")
            .text(function(d) {
                return d.name
            })

            force.on("tick", function() {
            edges.attr("x1", function(d) { return d.source.x; })
            .attr("y1", function(d) { return d.source.y; })
            .attr("x2", function(d) { return d.target.x; })
            .attr("y2", function(d) { return d.target.y; })
            nodes.attr("cx", function(d) { return d.x; })
            .attr("cy", function(d) { return d.y; })
            })

这是错误。请帮我说明为什么会发生这种情况

ps。这是书中的虚拟数据。我真的不明白为什么这行得通而我的不行。

var graph = {
        nodes: [
        { name: "Adam" },
        { name: "Bob" },
        { name: "Carrie" },
        { name: "Donovan" },
        { name: "Edward" },
        { name: "Felicity" },
        { name: "George" },
        { name: "Hannah" },
        { name: "Iris" },
        { name: "Jerry" }
        ],
        edges: [
        { source: 0, target: 1 },
        { source: 0, target: 2 },
        { source: 0, target: 3 },
        { source: 0, target: 4 },
        { source: 1, target: 5 },
        { source: 2, target: 5 },
        { source: 2, target: 5 },
        { source: 3, target: 4 },
        { source: 5, target: 8 },
        { source: 5, target: 9 },
        { source: 6, target: 7 },
        { source: 7, target: 8 },
        { source: 8, target: 9 }
        ]
        }

【问题讨论】:

    标签: javascript d3.js graph


    【解决方案1】:

    你的问题很简单。您只有 16 个节点:

    var graph = {
      nodes: [{
        Name: "b"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "b"
      }, {
        Name: "b"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "b"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "d"
      }, {
        Name: "d"
      }, {
        Name: "a"
      }, {
        Name: "c"
      }],
      links: [{
        source: 8,
        target: 3
      }, {
        source: 3,
        target: 5
      }, {
        source: 3,
        target: 6
      }, {
        source: 3,
        target: 7
      }, {
        source: 3,
        target: 11
      }, {
        source: 3,
        target: 12
      }, {
        source: 8,
        target: 0
      }, {
        source: 0,
        target: 13
      }, {
        source: 0,
        target: 14
      }, {
        source: 8,
        target: 9
      }, {
        source: 9,
        target: 17
      }, {
        source: 9,
        target: 18
      }, {
        source: 14,
        target: 15
      }, {
        source: 14,
        target: 16
      }, {
        source: 8,
        target: 10
      }]
    }
    
    console.log("number of nodes: " + graph.nodes.length)

    它们的索引从 0 变为 15(从零开始)。

    但是,在您的 links 数组中,您的源/目标高于此值,例如 17 或 18!那是行不通的。请注意,原始数据只有 10 个节点,并且边的数组以 9 作为源或目标的最大索引。

    这是您的代码和数据,将高于 15 的所有内容更改为其他数字:

    var graph = {
      nodes: [{
        Name: "b"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "b"
      }, {
        Name: "b"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "b"
      }, {
        Name: "c"
      }, {
        Name: "c"
      }, {
        Name: "d"
      }, {
        Name: "d"
      }, {
        Name: "a"
      }, {
        Name: "c"
      }],
      links: [{
        source: 8,
        target: 3
      }, {
        source: 3,
        target: 5
      }, {
        source: 3,
        target: 6
      }, {
        source: 3,
        target: 7
      }, {
        source: 3,
        target: 11
      }, {
        source: 3,
        target: 12
      }, {
        source: 8,
        target: 0
      }, {
        source: 0,
        target: 13
      }, {
        source: 0,
        target: 14
      }, {
        source: 8,
        target: 9
      }, {
        source: 9,
        target: 10
      }, {
        source: 9,
        target: 10
      }, {
        source: 14,
        target: 15
      }, {
        source: 14,
        target: 10
      }, {
        source: 8,
        target: 10
      }]
    }
    
    var w = 800;
    var h = 400;
    
    var svg = d3.select("body")
      .append("svg")
      .attr("width", w)
      .attr("height", h)
    
    var force = d3.forceSimulation(graph.nodes)
      .force("charge", d3.forceManyBody())
      .force("link", d3.forceLink(graph.links))
      .force("center", d3.forceCenter().x(w / 2).y(h / 2))
    
    var edges = svg.selectAll("line")
      .data(graph.links)
      .enter()
      .append("line")
      .style("stroke", "#ccc")
      .style("stroke-width", 1)
    
    var nodes = svg.selectAll("circle")
      .data(graph.nodes)
      .enter()
      .append("circle")
      .attr("r", 10)
    
    nodes.append("title")
      .text(function(d) {
        return d.name
      })
    
    force.on("tick", function() {
      edges.attr("x1", function(d) {
          return d.source.x;
        })
        .attr("y1", function(d) {
          return d.source.y;
        })
        .attr("x2", function(d) {
          return d.target.x;
        })
        .attr("y2", function(d) {
          return d.target.y;
        })
      nodes.attr("cx", function(d) {
          return d.x;
        })
        .attr("cy", function(d) {
          return d.y;
        })
    })
    &lt;script src="https://d3js.org/d3.v4.min.js"&gt;&lt;/script&gt;

    【讨论】:

    • 有道理,谢谢您的回复!源和目标编号分别高达 17 和 18,因为节点在数据库中的 id 为 17 或 18。认为这必须是正确的并不是很聪明,因为它在数据库中就是这样。我删除并添加了一些节点,因此 id 号最终高于节点数。我想我必须找到一种方法来使用 javascript 重新排列源编号和目标编号,对吧?谢谢
    猜你喜欢
    • 2020-08-29
    • 1970-01-01
    • 2018-12-01
    • 1970-01-01
    • 2023-03-20
    • 1970-01-01
    • 2020-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多