【问题标题】:d3 enter not placing datad3 输入不放置数据
【发布时间】:2017-01-30 01:33:45
【问题描述】:

使用 d3,我将 8760 个数据点(2013 年每小时一个)从 csv 读取到二维数组中,然后尝试将它们创建为 <svg> 元素中的圆圈。代码成功导入数据,我可以在浏览器的控制台中查看它。但是,enter 函数似乎没有应用数据来创建圆圈。不会引发任何错误。

代码:

  <script src="https://d3js.org/d3.v4.min.js"></script>
  <script>
  var w = 900, h = 500;
  var dataset = [];

  d3.csv("Jsorted2.csv", function(error, data) {
    dataset = data.map(function(d) { return [ +d["Load"], new Date(d["dtDateTime"]), +d["Month"], +d["Hour"], +d["DayofYear"], +d["NetLoad"]]; });
  });

  var svg = d3.select("body")
    .append("svg")
    .attr("width", w)
    .attr("height", h);

  svg.selectAll("circle")
    .data( dataset )
    .enter()
    .append("circle")
    .attr("cx", function(d,i) { return i; })
    .attr("cy", function(d,i) { return d[0]; })
    .attr("r", function(d,i) { return d[5]; });

</script>

数据加载正确:

Browser Inspector Console Screenshot

但圆圈不见了:

Browser Inspector Source Screenshot

如果我更改数据集的初始定义,我会发现不同的错误。如果我使用

var dataset = [[]];

数据仍在加载,但现在当 d3 尝试抓取数据时收到错误消息:

d3.v4.min.js:3 Error: <circle> attribute cy: Expected length, "NaN".
(anonymous function) 
@ d3.v4.min.js:3Q_ 
@ d3.v4.min.js:6K_ 
@ d3.v4.min.js:6(anonymous function) 
@ D3test4LD.html:29

d3 在创建圆圈方面更进一步:

<svg width="900" height="500">
<circle cx="0" cy="NaN"></circle>
</svg>

为什么 d3 不将数据加载到圆中?似乎 d3 没有按应有的方式将数据传递给 d,因为 d[0] 没有长度。如果我不能让它工作,我只会编写一个 Javascript for 循环来自己放置它们,但我想弄清楚为什么这不起作用。它看起来像一个类型转换问题,但我使用 + 导入数据,这应该将数据设置为数字。我什至可以在控制台中进行测试:

> typeof(dataset[0][0])
"number" 

请不要将 js for 循环作为解决方案。


更新

所以,在研究异步数据加载后,我确实解决了我的问题,如下面的答案。为了便于将来参考,以下是编写解决方案的一种方法:

setInterval(drawLD, 2000);

function drawLD(){
    svg.selectAll("circle")
      .data( dataset )
      .enter()
      .append("circle")
      .attr("cx", function(d,i) { return Math.round(i/8760); })
      .attr("cy", function(d,i) { return Math.round(d[0]/maxload); })
      .attr("r", function(d,i) { return 2; });
  }

【问题讨论】:

    标签: javascript csv d3.js svg


    【解决方案1】:

    d3.csv 是一个异步函数。创建圆圈的代码在您的 csv 数据返回之前执行。将您的 d3 代码放在回调中。

    <script>
      var w = 900, h = 500;
      var dataset = [];
    
      d3.csv("Jsorted2.csv", function(error, data) {
        dataset = data.map(function(d) { return [ +d["Load"], new Date(d["dtDateTime"]), +d["Month"], +d["Hour"], +d["DayofYear"], +d["NetLoad"]]; });
    
        var svg = d3.select("body")
        .append("svg")
        .attr("width", w)
        .attr("height", h);
    
      svg.selectAll("circle")
        .data( dataset )
        .enter()
        .append("circle")
        .attr("cx", function(d,i) { return i; })
        .attr("cy", function(d,i) { return d[0]; })
        .attr("r", function(d,i) { return d[5]; });
    
      });
    </script>
    

    【讨论】:

    • 感谢您的回复。所以更像这样? bl.ocks.org/syntagmatic/5113469 你建议我使用 SetInterval 吗?或者可能是触发圆圈绘制的更新按钮?
    • 不,加载 csv 数据时不要使用 setInterval 来“猜测”。我的答案是当您确定数据已加载时执行代码的标准 javascript 方式。回调函数仅在数据加载或失败时调用。
    猜你喜欢
    • 2014-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-29
    • 2016-07-29
    • 2012-10-28
    相关资源
    最近更新 更多