javascript - 如何在D3中监听频繁的SSE?

标签 javascript jquery d3.js server-sent-events

我无法找出在 D3 中绘制点时实现平滑过渡的方法。我有一个绘制世界地图的脚本。我正在监听服务器,该服务器向我提供事件的纬度和经度。我想在屏幕上绘制事件,使圆的半径在 1 秒内从 0 增加到 10。因为我正在监听服务器,所以我可以在一秒钟内获得多个数据点。当前一个点仍在转换时,我应该如何绘制另一个点?

这是我想出的代码,但我无法找出将 d3 类型转换添加到“圆”的方法,因为只有当您使用 d3.data([coords]) 时才有可能。进入()。在我看来,在这里使用 d3 似乎有点矫枉过正,因为我可以直接更改属性。

编辑:

为了稍微简化我的问题,我决定收集 1 秒的数据,然后一次性显示这些点。但是,我认为我无法理解 exit() 的本质,因为下面的代码没有删除前面的点并在坐标处创建新点。 Points.exit().remove 不起作用,因为它返回一个大小为 0 的数组,尽管坐标每次都会改变。而且,它会在 map 上连续显示第一组数据,之后不会更改任何内容。

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script type="text/javascript" src="//code.jquery.com/jquery-1.8.0.min.js"></script>
    <script type="text/javascript">
        $(document).ready(
                function() {
                    sse = new EventSource('/my_event_source');
                    sse.onmessage = function(message) {
                        console.log('A message has arrived!');
                        var data = JSON.parse(message.data);
                        data.data.forEach(function(d){
                          d.lat = +d.lat;
                          d.lg = +d.lg;
                        });
                        console.log(data.data)
                        plot(data.data);
                       }
                })
    </script>

    <style>

.point{
  fill:rgb(247,148, 32);
  stroke:black;
  stroke-width:0.7;
  opacity:0.7;
}
    </style>

    <script type ="text/javascript">
      function draw(geo_data){
        "use strict";
        var margin = 75,
         width = 1920 -margin,
         height = 1080 -margin; 

      var svg = d3.select('body')
                    .append("svg")
                    .attr('class',"main")
                    .attr('width', width+margin)
                    .attr('height', height+margin)

      var svg2 = svg.append('g')
                    .attr('class','map');


      // convrt the long, lat to pixels ()x,y
      var projection = d3.geo.mercator()
                          .scale(220)
                          .translate([width/2, height/1.5]);
      //svg objects
      var path = d3.geo.path().projection(projection);
      var map = svg2.selectAll('path')
                  .data(geo_data.features)
                  .enter()
                  .append('path')
                  .attr('d', path)
                  .style('fill','rgb(9,157,217)')
                  .style('stroke','black')
                  .style('stroke-width', 0.5);

      svg.append("g").attr("class","point");
      }

      function plot(data){
        "use strict";
        var margin = 75,
         width = 1920 -margin,
         height = 1080 -margin;

         var spot = d3.select('svg.main').select("g.point");

        // convrt the long, lat to pixels ()x,y
         var projection = d3.geo.mercator()
                             .scale(220)
                             .translate([width/2, height/1.5]);



          var coords = data.map(function(d) {
            return projection([d.lg, d.lat]);
          });

          var points = spot.selectAll("circle")
                        .data(coords);

          points.exit().remove();

          points.enter()
                .append("circle")
                .classed("circle", true)
                .attr('cx', function(d){return d[0];})
                .attr('cy', function(d){return d[1];})
                .attr('r', 10);
        }
    </script>
  </head>

  <body>
    <script type = "text/javascript">
    /*Use d3 to load the GeoJSON file*/
    d3.json("/static/world_countries.json", draw);
    </script>
  </body>

</html>

最佳答案

您应该查看 Mike Bostock 的 Thinking with Joins文章。您遇到的问题是概念化如何使用 D3 来操作项目数组,但只有 D3 为最近添加到数组中的新项目制作动画。这是通过 .data().enter() 命令完成的。

我整理了一个您想要实现的目标的示例,省略了地理维度。该示例包含三个主要部分:变量的初始化、每次将新项目添加到数组时运行的绘制函数以及随机添加项目然后调用 draw() 的服务器模拟。

您将看到所有神奇的事情都发生在draw()函数中。即使我们反复将不断增长的数据数组传递给函数,该函数也只会对新添加的数据项进行动画处理。

https://jsbin.com/qoqalufihe/edit?html,output

关于javascript - 如何在D3中监听频繁的SSE?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32914778/

相关文章:

javascript - 通过javascript为taglib设置属性

javascript - 使用 php 获取其他页面的具有多个分配值的 Href 标签

javascript - 点击功能不起作用,如果我评论 $ ('#tablenew' ).dataTable( {});它可以工作,但我也想要数据表

javascript - 在 d3.js 中插入子元素

JavaScript 排序数字未按预期工作

javascript - 无论在哪里使用,我如何触发图像重新加载(CSS 背景图像、伪元素、样式属性、img 标签)

非表单元素的 jQuery 更改事件

javascript - 从jquery获取多个值并将其发布到php

javascript - 使用纬度/经度输入拖动点

javascript - D3键功能参数未定义