Merging data in d3.js

2020-07-20 03:55发布

问题:

I'm Pythonista and trying to learn d3.js (smile).

I have a server with a socket. My page subscribes to it. Server sends updates as JSON '[["id0", 0.38], ["id1", 0.70], ["id8", 0.71]]'. I wrote the following simple page:

<!doctype html>
<html>
  <head>
    <title>WebSockets</title>
  </head>
  <body>
    <script src="http://d3js.org/d3.v2.js"></script>
    <script>
      var ws = new WebSocket("ws://localhost:9999/updates");
      ws.onmessage = function(message)
      {
        var my_data = JSON.parse(message.data);
        var dd = d3.selectAll("#messages")
          .append("div")
          .selectAll("div")
          .data(my_data)
          .enter()
          .append("div")
          .attr("id",function(d){return d[0];})
          .text(function(d){return d[1];})
      }
    </script>
    <div id='messages'></div>
  </body>
</html>

It works fine! WS receives the data. In the div#messages it creates a new div. And then places data from msg into the div#id*. So, after many iteration I have:

...
<div id="messages">
  <div>
    <div id="id0">0.83</div>
    <div id="id1">0.06</div>
    <div id="id2">0.33</div>
  </div>
  <div> 
    ... 
  </div>
  <div> 
    ... 
  </div>
  ...
</div>
...

How to modify the code to make it work like this:

Having

...
<div id='messages'>
  <div id='id0'>0.25</div>
  <div id='id1'>0.05</div>
  <div id='id2'>0.25</div>
</div>
...

Recieve

'[["id0", 0.38], ["id1", 0.70], ["id8", 0.71]]'

Get in result

...
<div id='messages'>
  <div id='id0'>0.38</div>
  <div id='id1'>0.70</div>
  <div id='id2'>0.25</div>
  <div id='id8'>0.71</div>
</div>
...

I mean "if given id in #messages then update it; else append it to the end".

I could do this with loops, but doc says that it shall be done with enter() and exit()..

It seems that in these articles (circle, join) is written how to do that. The problem is that I do not understand ideas of data synchronization in these articles at all. I hope that the code will help me understand this.


PS: I do all the logic in Python, however, I must show data on the page with minimal redrawing. And everyone says that d3 - is very easy and convenient. I read the docs and it seems that d3 is good framework, but I have some troubles with fundamentals.


PPS: If data should be transmitted in other way - there is no problem.



UPDATE

With the help of console, I found, that

d3.select("#messages")
  .select("div")
  .selectAll("div")
  .data([["id0",0]], function(d){return d[0];})
  .enter()

gives me array [null]

d3.select("#messages")
  .select("div")
  .selectAll("div")
  .data([["id0",0]], function(d){return d[0];})

gives me array [HTMLDivElement] with HTMLDivElement.__data__ == ["id0",0]

and

d3.select("#messages")
  .select("div")
  .selectAll("div")
  .data([["id0",0]], function(d){return d[0];})
  .exit()

gives [null, HTMLDivElement, HTMLDivElement] with "id1" and "id2" in HTMLDivElement.__data__[0] respectively.

Any idea What next?

回答1:

I found that this seems to work.. but what does it really do?

var my_data = JSON.parse(message.data);
var my_selection = d3.selectAll("#messages")
  .selectAll("div")
  .data(my_data, function(d){return d[0];})
my_selection
  .enter()
  .append("div")
  .attr("id",function(d){return d[0];})
my_selection
  .text(function(d){return d[1];})

If nobody can answer, may be somebody can explain?