【问题标题】:Links not visible when loading json data dynamically into D3 Network Visualization将 json 数据动态加载到 D3 网络可视化中时链接不可见
【发布时间】:2018-06-14 05:50:05
【问题描述】:

我有一个节点的 json 文件,然后是用源和目标指定的链接。

    {
    "links":[
        {"_id": "5a4b2866235fa755b6576903", "target": 6746, "source": 2169},
        {"_id": "5a4b2866235fa755b65768e3", "target": 6746, "source": 6357},
        {"_id": "5a4b2866235fa755b6576641", "target": 7045, "source": 8590}
            ],

    "nodes":[
        {"_id": "5a4b281e235fa755b6576340", "id": 6746, "Citation": "Chandler", "citedNo": "0", "size": 10},
        {"_id": "5a4b281d235fa755b657447f", "id": 1195, "Citation": "Aaron", "citedNo": "0", "size": 0},
        {"_id": "5a4b281e235fa755b657591f", "id": 4438, "Citation": "Chris", "citedNo": "0", "size": 10},
        {"_id": "5a4b281e235fa755b6575f31", "id": 7045, "Citation": "Brittany", "citedNo": "0", "size": 10},
        {"_id": "5a4b281e235fa755b6575f27", "id": 2169, "Citation": "James", "citedNo": "0", "size": 10},
        {"_id": "5a4b281e235fa755b6575ecb", "id": 6357, "Citation": "David", "citedNo": "0", "size": 10},
        {"_id": "5a4b281e235fa755b6575750", "id": 8590, "Citation": "Kris", "citedNo": "0", "size": 10}
            ]
    }

当我从文件中加载上述数据时,会显示链接。当我动态执行此操作时,没有可见的链接。

为什么是动态的?关键字在 MongoDB 上使用 ElasticSearch 进行搜索,有一个由节点、链接(源和目标)创建的 json,并在 js 中引用用于创建 D3 网络可视化。

我需要动态执行此操作,因为搜索用例将是无限的,并且过滤和存储如此多版本的 json 文件将是次优的。

创建数组的代码如下

    var arr = new Object;
    arr["nodes"] = nodearray;
    arr["links"] = linkarray;

下面是创建 D3 网络可视化的脚本

    d3.json('d3datap.json', function(error, graph) {
                      // console.log(JSON.stringify(arr));
                      var graph = JSON.parse(JSON.stringify(arr));
                      console.log(graph.nodes);
                      console.log(graph.links);
                      const width = 1200;
                      const height = 500;

                      const mouseOverFunction = function (d) {
                        const circle = d3.select(this);

                        node.append("text")
                        .attr("x", 12)
                        .attr("dy", ".35em")
                        .text(function(d) { return d.Party; });

                        node
                          .transition(500)
                            .style('opacity', o => {
                              const isConnectedValue = isConnected(o, d);
                              if (isConnectedValue) {
                                return 1.0;
                              }
                              return 0.2
                            })
                            .style('fill', (o) => {
                              let fillColor;
                              if (isConnectedAsTarget(o, d) && isConnectedAsSource(o, d)) {
                                fillColor = 'green';
                              } else if (isConnectedAsSource(o, d)) {
                                fillColor = 'red';
                              } else if (isConnectedAsTarget(o, d)) {
                                fillColor = 'blue';
                              } else if (isEqual(o, d)) {
                                fillColor = 'hotpink';
                              } else {
                                fillColor = '#000';
                              }
                              return fillColor;
                            });

                        link
                          .transition(500)
                            .style('stroke-opacity', o => (o.source === d || o.target === d ? 1 : 0.2))
                            .transition(500)
                            .attr('marker-end', o => (o.source === d || o.target === d ? 'url(#arrowhead)' : 'url()'));

                        circle
                          .transition(500)
                            .attr('r', () => 1.4 * nodeRadius(d));
                      };

                      const mouseOutFunction = function () {
                        const circle = d3.select(this);

                        svg.selectAll("text").remove();

                        node
                          .transition(500);

                        link
                          .transition(500);

                        circle
                          .transition(500)
                            .attr('r', nodeRadius);
                      };

                      const nodes = graph.nodes;
                      const links = graph.links;

                      const simulation = d3.forceSimulation()
                        .force('link', d3.forceLink().id(d => d.id))
                        .force('charge', d3.forceManyBody())
                        .force('center', d3.forceCenter(width / 2, height / 2));

                        // const simulation = d3.forceSimulation()
                        //   .nodes(nodes)
                        // .links(links)
                        // .charge(-3000)
                        // .friction(0.6)
                        // .gravity(0.6)
                        // .size([width, height])
                        // .start();

                      const svg = d3.select('#vis').append('svg')
                        .attr('width', width)
                        .attr('height', height)
                        .classed("svg-content", true);

                      let link = svg.selectAll('line')
                        .data(graph.links)
                        .enter().append('line');

                      let node = svg.selectAll('.node')
                        .data(graph.nodes)
                        .enter().append("g")
                          .attr('class', 'node');

                      node.append("svg:a")
                        .append('circle')
                          .attr("r", nodeRadius)
                          .on('mouseover', mouseOverFunction)
                          .on('mouseout', mouseOutFunction)
                          .call(d3.drag()
                            .on("start", dragstarted)
                            .on("drag", dragged)
                            .on("end", dragended))
                          .on("dblclick",function(d){
                              window.open(d.url, '_blank')});



                      svg
                        .append('marker')
                        .attr('id', 'arrowhead')
                        .attr('refX', 6 + 7) // Controls the shift of the arrow head along the path
                        .attr('refY', 2)
                        .attr('markerWidth', 6)
                        .attr('markerHeight', 4)
                        .attr('orient', 'auto')
                        .append('path')
                          .attr('d', 'M 0,0 V 4 L6,2 Z');

                      link
                        .attr('marker-end', 'url()');

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

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

                      let linkedByIndex = {};
                      links.forEach((d) => {
                        linkedByIndex[`${d.source.index},${d.target.index}`] = true;
                      });

                      function isConnected(a, b) {
                        return isConnectedAsTarget(a, b) || isConnectedAsSource(a, b) || a.index === b.index;
                      }

                      function isConnectedAsSource(a, b) {
                        return linkedByIndex[`${a.index},${b.index}`];
                      }

                      function isConnectedAsTarget(a, b) {
                        return linkedByIndex[`${b.index},${a.index}`];
                      }

                      function isEqual(a, b) {
                        return a.index === b.index;
                      }

                      function ticked() {
                        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 => `translate(${d.x},${d.y})`);
                        }

                      function nodeRadius(d) { return Math.pow(40.0 * d.size, 1 / 3); }

                      function dragstarted(d) {
                        if (!d3.event.active) simulation.alphaTarget(0.3).restart();
                        d.fx = d.x;
                        d.fy = d.y;
                      }

                      function dragged(d) {
                        d.fx = d3.event.x;
                        d.fy = d3.event.y;
                      }

                      function dragended(d) {
                        if (!d3.event.active) simulation.alphaTarget(0);
                        d.fx = null;
                        d.fy = null;
                      }
                      });

CSS 在下面

    .node circle {
          stroke: white;
          stroke-width: 1.5px;
          opacity: 1.0;
        }

        line {
          stroke: black;
          stroke-width: 1.5px;
          stroke-opacity: 1.0;
        }

我可以在控制台中看到 json 的数据,但链接不可见/不存在。我搜索了所有关于将 json 动态加载到 D3 中的问题,但找不到解决问题的方法。如果有人能指出这是什么问题,我将不胜感激。

【问题讨论】:

    标签: javascript json mongodb d3.js visualization


    【解决方案1】:

    d3.json 是一个异步调用。您似乎在 json 调用上方的某处创建了 arr 对象:

    d3.json('d3datap.json', function(error, graph) {
           // graph is passed in, but arr is used??
                      // console.log(JSON.stringify(arr));
                      var graph = JSON.parse(JSON.stringify(arr));
    

    因此,当 d3 使用它时,arr 对象可能会或可能不会完全形成。当您console.log 图形时,chrome 会在异步调用完成后更新该对象,因此当您查看它时它可能包含所有数据,但 d3 没有获取数据。您的代码应该使用您从 d3.json 调用中获得的 graph 值。

    如果您发布有关您的 arr 生成的附加代码以及为什么它高于您的 d3.json 调用,那么我可以更新此答案。一般来说,最好发布整个代码块而不是发布其中的一部分(最好提供指向 bl.ocks.org 或 blockbuilder.org 或 codepen 版本的代码的链接)。

    【讨论】:

    • 是的,根据您的建议,我已将代码模块化并添加了 d3-queue 以使其正常工作。但是,现在收到“无效回调”错误。
    猜你喜欢
    • 2019-08-14
    • 2014-03-06
    • 1970-01-01
    • 2016-09-01
    • 2019-10-30
    • 2019-08-10
    • 2011-10-23
    • 2013-12-13
    • 2021-09-19
    相关资源
    最近更新 更多