从d3中的局部变量读取节点数据

时间:2018-06-02 21:59:40

标签: json d3.js

如何从局部变量jsonNodes创建d3图表(JSON数据)而不是从文件中读取,我使用的示例是Andrew-Reid’s online example on bl.ocks

以下是我正在尝试的代码,按钮' Go'正在调用refresh函数以使用jsonNodes变量刷新图形。 (我实际上是调用WebSocket服务来填充jsonNodes但是到目前为止我刚刚在函数中对其进行了硬编码。)

当我点击' Go'按钮,它什么都不做。

  <canvas width="960" height="500"></canvas>
  <body>
      <button id="refresh" onclick="refresh();">Go</button>
  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script>
  var canvas = document.querySelector("canvas"),
      context = canvas.getContext("2d"),
      width = canvas.width,
      height = canvas.height;

  var jsonNodes;

  function refresh(){
    jsonNodes =  {
    "nodes": [
      {"id": "Myriel", "group": 1},
      {"id": "Napoleon", "group": 1},
      {"id": "Mlle.Baptistine", "group": 1} ],
      "links": [
      {"source": "Napoleon", "target": "Myriel", "value": 1} ]
       } ;

        simulation
        .nodes(jsonNodes.nodes)
        .force("link")
        .links(jsonNodes.links);   
  };

  var simulation = d3.forceSimulation()
      .force("link", d3.forceLink().id(function(d) { return d.id; }))
      .force("charge", d3.forceManyBody())
      .force("center", d3.forceCenter(width / 2, height / 2));

  d3.json("../data/miserables.json", function(error, graph) {
    if (error) throw error;

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

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

    d3.select(canvas)
        .call(d3.drag()
            .container(canvas)
            .subject(dragsubject));

    function ticked() {
      var margin = 20;
      graph.nodes.forEach(function(d) { 
        d.x = Math.max(margin, Math.min(width - margin, d.x))
        d.y = Math.max(margin, Math.min(height - margin, d.y))
      })

      context.clearRect(0, 0, width, height);

      context.beginPath();
      graph.links.forEach(drawLink);
      context.strokeStyle = "#aaa";
      context.stroke();

      context.beginPath();
      graph.nodes.forEach(drawNode);
      context.fill();
      context.strokeStyle = "#fff";
      context.stroke();
    }

    function dragsubject() {
      return simulation.find(d3.event.x, d3.event.y);
    }
  });

  function drawLink(d) {
    context.moveTo(d.source.x, d.source.y);
    context.lineTo(d.target.x, d.target.y);
  }

  function drawNode(d) {
    context.moveTo(d.x + 3, d.y);
    context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
  }
  </script>
  </body>

1 个答案:

答案 0 :(得分:1)

根据您使用示例代码更新的帖子,很少有可能导致无法获得所需结果的内容。 首先,我可以看到jsonNodes已经是所需格式的对象。  其次,由于数据在变量中已经是所需的格式,因此您无需使用d3.json("../data/miserables.json", function(error, graph) { if (error) throw error;对其进行解析。

同样在Andrew Reid的例子中,他使用对象graph,在您的情况下jsonNodes。因此,无论何时,您都会看到graph.nodesgraph.links将其替换为jsonNodes.nodesjsonNodes.links。更改所有单个位置的更简单的替代方法是将数据从jsonNodes传输到名为graph的变量,并使用graph变量,如Andrew Reid的示例中所示。

最后,您声明模拟的顺序是错误的。你在打电话

    simulation
        .nodes(jsonNodes.nodes)
        .force("link")
        .links(jsonNodes.links);   
  };

之前

var simulation = d3.forceSimulation()
      .force("link", d3.forceLink().id(function(d) { return d.id; }))
      .force("charge", d3.forceManyBody())
      .force("center", d3.forceCenter(width / 2, height / 2));

这是相反的。

这是一个为您准备好一切的东西: https://plnkr.co/edit/LcsGes?p=preview

其他一些例子:http://jsfiddle.net/DavidHoksza/0d7en4po/直接使用变量中的数据。但是,请记住,此示例使用d3 v3,并且力模拟的语法已更改。还有更多的例子直接在力模拟中使用变量:http://blockbuilder.org/kenpenn/268878b410ddb1201277be3f0305d566 您可以使用http://blockbuilder.org/search

搜索更多示例

我希望这会有所帮助。如果没有,请为我创建plunker / block来检查你到底发生了什么。并将更多数据填充到jsonNodes变量中。