绘制没有数据的d3.js行时出错

时间:2014-07-07 16:32:28

标签: javascript d3.js

我有一条d3.js折线图,有多行。用户可以更改与每一行关联的过滤器,这会更改绘制的值以及图表更新。

这一切都运行正常,但如果用户选择导致行没有匹配值的过滤器,我会在控制台中收到此错误:

Error: Invalid value for <path> attribute d=""          d3.js:8481
attrNull                                                d3.js:8481
(anonymous function)                                    d3.js:8653
d3_class.forEach                                        d3.js:275
start                                                   d3.js:8652
(anonymous function)                                    d3.js:8646
d3_timer_mark                                           d3.js:2085
d3_timer_step                                           d3.js:2065

用户可见的内容很好 - 当图表更新时,线条(显然)不会被绘制。但是我想摆脱这个错误!这是输入/更新/删除行的代码:

var line = g.selectAll('path.line')
            .data(function(d) { return d; },
                  function(d) { return d.id; });

line.enter().append('path')
      .attr('class', 'line')
      .attr('id', function(d) { return lineCSSID(d.id); })
      .style('stroke', function(d) { return d.color; });

line.data(function(d) { return d; })
    .transition()
    .attr('d', function(d) { return chartLine(d.values); });

line.exit().remove();

调用return chartLine(d.values);d.values为空数组时发生错误。我能做些什么会让它更优雅地失败?

如果它影响答案:用户可以再次更改该行的过滤器,如果这会导致匹配数据,则会重新绘制该行。

3 个答案:

答案 0 :(得分:1)

在将数据添加到图表之前,我最后省略了没有数据的任何行。

例如,如果(在我的问题代码之前的某个地方)我有类似的东西,其中data是一个对象数组,每个对象代表图表上的一行:

var svg = d3.select('.chart')
              .selectAll('svg')
                .data([data]);

然后在此之前我现在这样做:

data = data.filter(function(d){ return d.values.length > 0; });

这可确保任何没有数据点的行都不会传递给图表。

更新:我意识到如果 all 这些行的过滤器导致没有匹配的值,那么我在尝试计算{{1对于x轴。所以我现在有这样的事情:

domain

答案 1 :(得分:0)

您是否尝试添加一些条件,以便只有在d.values不是空数组时才会返回?

if(d.values.length > 0){
    return chartLine(d.values);
}

答案 2 :(得分:0)

我迟到了,但考虑使用d3.line并声明使用line.defined定义数据的位置。这是一种用于容纳缺失数据的d3内置方法。

例如:

var line = d3.line()
    .defined(function(d) { return d[hasData]; })
    .x(function(d) { return x(d.x); })
    .y(function(d) { return y(d.y); });

如果对象包含数据,function(d) { return d[hasData]; }应返回truthy值,否则返回false。如果返回false,则d3将跳过呈现该特定数据元素。

如果您的数据是:

var data = [{name:"foo", value:1, hasData:true}, {name:"bar", value:0, hasData:false}]

d3.line的上述设置将跳过第二个对象("bar")。此外,由于0是假的,而且任何正intfloat都是真实的,您只需使用function(d) { return d.value; }

迈克自己做了一个例子here

干杯。