d3.js JS D3使用WebSocket更新力图

xiozqbni  于 2022-11-12  发布在  其他
关注(0)|答案(1)|浏览(262)

**上下文:**我有一个管理设备的Django服务器,我想显示这些设备之间的通信图,我决定使用D3力图来实现这个目的,Django服务器将通过Redis发送一个带有WebSocket的json,我想让客户端读取json并打印图形。

到目前为止,我已经能够打印静态图形,但我不能管理更新它的生活。

有用的链接:

  • 来自This示例的核心代码。
  • 我试着跟着This走,但我觉得方向不对。
    **目标:**使用WebSocket真实的更新力图。

我的JS代码:

var graph = {
  "nodes": [
            {"id": "Agent_1", "group": 1},
            {"id": "Agent_2", "group": 2},
            {"id": "Agent_3", "group": 1},
            {"id": "Agent_4", "group": 3}
        ],
  "links": []
};

const comSocket = new WebSocket(
  'ws://'
  + window.location.host
  + '/ws/com/'
);

comSocket.onmessage = function (e) {
  graph = JSON.parse(e.data).message;
  console.log(graph);

  simulation.nodes(graph.nodes);
  simulation.force("link").links(graph.links);
  simulation.alpha(1).restart();
  };

var svg = d3.select("svg"),
    width = +svg.attr("width"),
    height = +svg.attr("height");

var color = d3.scaleOrdinal(d3.schemeCategory20);

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

  var link = svg.append("g").attr("class", "links").selectAll("line")
  .data(graph.links).enter().append("line")
  .attr("stroke-width", function(d) { return Math.sqrt(d.value); });

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

  var circles = node.append("circle")
    .attr("r", 20)
    .attr("fill", function(d) { return color(d.group); });

  var lables = node.append("text").text(function(d) {return d.id;}).attr('x', 16).attr('y', 13);

  node.append("title").text(function(d) { return d.id; });

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

  function ticked() {
    link
        .attr("x1", function(d) { return d.source.x; })
        .attr("y1", function(d) { return d.source.y; })
        .attr("x2", function(d) { return d.target.x; })
        .attr("y2", function(d) { return d.target.y; });

    node
        .attr("transform", function(d) {
          return "translate(" + d.x + "," + d.y + ")";
        })
  };

使用上面的代码会产生以下错误:

Uncaught TypeError: Cannot read properties of undefined (reading 'length')

在以下行:

simulation.nodes(graph.nodes);

在onmessage()中
数据值是一个json,结构和var图(第1行)一样,所以不知道为什么它能正确初始化图,却不能刷新相同的值..:

{'nodes': [{'id': 'Agent_0', 'group': 1}, {'id': 'Agent_1', 'group': 2}, {'id': 'Agent_2', 'group': 1}, {'id': 'Agent_3', 'group': 3}], 'links': [{'source': 'Agent_0', 'target': 'Agent_2', 'value': 1}, {'source': 'Agent_0', 'target': 'Agent_1', 'value': 3}, {'source': 'Agent_0', 'target': 'Agent_3', 'value': 5}, {'source': 'Agent_1', 'target': 'Agent_3', 'value': 3}, {'source': 'Agent_2', 'target': 'Agent_3', 'value': 5}, {'source': 'Agent_1', 'target': 'Agent_2', 'value': 5}]}
gkn4icbw

gkn4icbw1#

这是服务器端问题,发送了错误的类型。
最后我也更新了代码到最新版本(只有颜色需要更新).这里是最终的工作版本:

var graph = {
 "nodes": [
           {"id": "Agent_0", "group": 1},
           {"id": "Agent_1", "group": 2},
           {"id": "Agent_2", "group": 1},
           {"id": "Agent_3", "group": 3}
       ],
 "links": []
};

var svg = d3.select("svg"),
   width = +svg.attr("width"),
   height = +svg.attr("height");

var color = d3.schemeCategory10;

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

 var link = svg.append("g").attr("class", "links").selectAll("line").data(graph.links).enter().append("line")
 .attr("stroke-width", function(d) { return Math.sqrt(d.value); });

 var node = svg.append("g").attr("class", "nodes").selectAll("g").data(graph.nodes).enter().append("g")
 var circles = node.append("circle").attr("r", 20).attr("fill", function(d) { return color[d.group]; });
 var lables = node.append("text").text(function(d) {return d.id;}).attr('x', 16).attr('y', 13);

 node.append("title").text(function(d) { return d.id; });

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

 function ticked() {
   link
       .attr("x1", function(d) { return d.source.x; })
       .attr("y1", function(d) { return d.source.y; })
       .attr("x2", function(d) { return d.target.x; })
       .attr("y2", function(d) { return d.target.y; });

   node
       .attr("transform", function(d) {
         return "translate(" + d.x + "," + d.y + ")";
       })
 };

const comSocket = new WebSocket(
 'ws://'
 + window.location.host
 + '/ws/com/'
);

comSocket.onmessage = function (e) {
 graph = JSON.parse(e.data).message;
 console.log(graph);
 console.log(typeof graph);

 svg.selectAll("*").remove();
 link = svg.append("g").attr("class", "links").selectAll("line").data(graph.links).enter().append("line")
 .attr("stroke-width", function(d) { return Math.sqrt(d.value); });

 node = svg.append("g").attr("class", "nodes").selectAll("g").data(graph.nodes).enter().append("g")
 circles = node.append("circle").attr("r", 20).attr("fill", function(d) { return color[d.group]; });
 lables = node.append("text").text(function(d) {return d.id;}).attr('x', 16).attr('y', 13);

 node.append("title").text(function(d) { return d.id; });

 simulation.nodes(graph.nodes).on("tick", ticked);
 simulation.force("link").links(graph.links);
 simulation.alpha(1).restart();
 };

相关问题