Ссылки не видны при динамической загрузке данных json в D3 Network Visualization

1

У меня есть 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}
            ]
    }

Когда я загружаю вышеуказанные данные из файла, появляются ссылки. Когда я делаю это динамически, ссылки не отображаются.

Почему динамически? Ключевое слово выполняется с помощью ElasticSearch на MongoDB, создается 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, но не смог найти решение моей проблемы. Если кто-нибудь может указать, в чем проблема с этим, я был бы очень признателен.

Теги:
d3.js
visualization

1 ответ

1

d3.json - асинхронный вызов. Кажется, вы создаете объект arr где-то выше вашего json-вызова:

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));

Поэтому объект arr может или не может быть полностью сформирован, когда d3 его использует. Когда вы console.log, хром обновляет этот объект после завершения асинхронного вызова, поэтому может показаться, что он содержит все данные, когда вы смотрите на него, но d3 не получает данные. Ваш код должен использовать значение graph которое вы получаете от вызова d3.json.

Если вы разместите дополнительный код о своем генерации arr и почему он выше вашего вызова d3.json я могу обновить этот ответ. В общем, лучше разместить весь блок кода, а не размещать его в битах (и лучше всего предоставить ссылку на bl.ocks.org или blockbuilder.org или кодовую версию кода).

  • 0
    Да, согласно вашему совету, я модулировал код, а также добавил d3-очередь, чтобы он работал. Тем не менее, теперь получаю ошибку «Неверный обратный вызов».

Ещё вопросы

Сообщество Overcoder
Наверх
Меню