Links not showing for Network Visualization - Creating d3.json from input of MongoDB query from ES

62 views
Skip to first unread message

Clint R

unread,
Jan 9, 2018, 3:33:09 AM1/9/18
to d3-js

Trying to create a network visualization from the example : http://bl.ocks.org/micahstubbs/e5d0c64e487a8920e6b775f1244f8486



I have a json file of nodes and then the links specified with source and target.



{
    "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}
            ]
    }



When I load the above data from within the file, the links show up. When I do this dynamically, no links are visible.


Why dynamically? The keyword is searched using ElasticSearch on MongoDB, there is a json created with nodes, links (sources and targets) and that is referenced in the js for creating the D3 network visualization.


I need to do this dynamically since the search use cases would be limitless and filtering and storing so many versions of json files would be sub-optimal.

Code for creating the arrays is below


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

Script for creating D3 network visualization is below

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 is below
    .node circle {
          stroke: white;
          stroke-width: 1.5px;
          opacity: 1.0;
        }

        line {
          stroke: black;
          stroke-width: 1.5px;
          stroke-opacity: 1.0;
        }
I can see the data for the json in the console but the links are not visible/ not there.
I searched all the questions on dynamic loading of json into D3 but couldn't find a solution to my problem.
If anyone can point out what is the problem with this, I'd appreciate it a lot.
Reply all
Reply to author
Forward
0 new messages