将json数据动态加载到D3网络可视化中时,链接不可见

时间:2018-01-04 13:21:43

标签: javascript json mongodb d3.js visualization

我有一个节点的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中的所有问题但是找不到我的问题的解决方案。如果有人能指出这有什么问题,我会非常感激。

1 个答案:

答案 0 :(得分: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没有获取数据。您的代码应使用graph调用中获得的d3.json值。

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