d3 <path>的值无效

时间:2015-10-29 04:27:10

标签: javascript d3.js

我是d3.js的新手,正在关注http://code.tutsplus.com/tutorials/building-a-multi-line-chart-using-d3js-part-2--cms-22973的示例,为我的应用程序构建嵌套时间序列。

但是,尽管数据看起来像示例

中的嵌套数据,但我遇到了这个错误
Error: Invalid value for <path> attribute d="MNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaN"

我的代码在这里,jsfiddle是http://jsfiddle.net/absail/h9hds98f/

nested_data = [{"key":"False","values":[{"date":"09/04/2015","val":0},{"date":"09/05/2015","val":222},{"date":"09/06/2015","val":168},{"date":"09/07/2015","val":203},{"date":"09/08/2015","val":219},{"date":"09/09/2015","val":237},{"date":"09/10/2015","val":241},{"date":"09/11/2015","val":397},{"date":"09/12/2015","val":158},{"date":"09/13/2015","val":154},{"date":"09/14/2015","val":193},{"date":"09/15/2015","val":202},{"date":"09/16/2015","val":218},{"date":"09/17/2015","val":466},{"date":"09/18/2015","val":439},{"date":"09/19/2015","val":278},{"date":"09/20/2015","val":271},{"date":"09/21/2015","val":475},{"date":"09/22/2015","val":494},{"date":"09/23/2015","val":498},{"date":"09/24/2015","val":503},{"date":"09/25/2015","val":437},{"date":"09/26/2015","val":286},{"date":"09/27/2015","val":280},{"date":"09/28/2015","val":496},{"date":"09/29/2015","val":514}]},{"key":"True","values":[{"date":"09/05/2015","val":3170},{"date":"09/11/2015","val":8643},{"date":"09/04/2015","val":0},{"date":"09/08/2015","val":6146},{"date":"09/12/2015","val":2414},{"date":"09/14/2015","val":5711},{"date":"09/19/2015","val":4118},{"date":"09/26/2015","val":3990},{"date":"09/06/2015","val":2565},{"date":"09/09/2015","val":6426},{"date":"09/13/2015","val":2514},{"date":"09/15/2015","val":5690},{"date":"09/16/2015","val":6222},{"date":"09/17/2015","val":10858},{"date":"09/18/2015","val":9718},{"date":"09/20/2015","val":4006},{"date":"09/21/2015","val":11135},{"date":"09/23/2015","val":11264},{"date":"09/25/2015","val":8831},{"date":"09/27/2015","val":3984},{"date":"09/28/2015","val":11554},{"date":"09/07/2015","val":5562},{"date":"09/10/2015","val":6505},{"date":"09/22/2015","val":11405},{"date":"09/24/2015","val":11411},{"date":"09/29/2015","val":12086}]}];
var parseDate = d3.time.format("%m/%d/%Y").parse;

var color = d3.scale.category10();
var vis = d3.select("#visualisation"),
WIDTH = 1000,
HEIGHT = 500,
MARGINS = {
    top: 50,
    right: 20,
    bottom: 50,
    left: 50
},

lSpace = WIDTH/nested_data.length;
xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(nested_data, function(d) {
    return d.date;
}), d3.max(data, function(d) {
    return d.date;
})]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(nested_data, function(d) {
    return d.val;
}), d3.max(data, function(d) {
    return d.val;
})]),
xAxis = d3.svg.axis()
.scale(xScale),
yAxis = d3.svg.axis()
.scale(yScale)
.orient("left");

vis.append("svg:g")
  .attr("class", "x axis")
  .attr("transform", "translate(0," + (HEIGHT - MARGINS.bottom) + ")")
  .call(xAxis);
vis.append("svg:g")
  .attr("class", "y axis")
  .attr("transform", "translate(" + (MARGINS.left) + ",0)")
  .call(yAxis);

var lineGen = d3.svg.line()
.x(function(d) {
    return xScale(d.date);
})
.y(function(d) {
    return yScale(d.val);
});
// .interpolate("basis");

// Loop through each symbol / key
nested_data.forEach(function(d, i) {

    vis.append('svg:path')
    .attr('d', lineGen(d.values))
    .attr('stroke', function(d,j) { 
            return "hsl(" + Math.random() * 360 + ",100%,50%)";
    })
    .attr('stroke-width', 2)
    .attr('id', 'line_'+d.key)
    .attr('fill', 'none');

    vis.append("text")
        .attr("x", (lSpace/2)+i*lSpace)
        .attr("y", HEIGHT)
        .style("fill", "black")
        .attr("class","legend")
        .on('click',function(){
            var active   = d.active ? false : true;
            var opacity = active ? 0 : 1;
            d3.select("#line_" + d.key).style("opacity", opacity);
            d.active = active;
        })
        .text(d.key);

});

我意识到这是其他人面临的常见错误,但似乎每次解决方案都不同。一些建议包括解析日期,但似乎并没有为我解决问题。任何帮助将不胜感激,因为我已经盯着这几个小时了。谢谢!

2 个答案:

答案 0 :(得分:1)

错误1:

计算最大值和最小值的方法是错误的:

yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(nested_data, function(d) {
    return d.val;
}), d3.max(data, function(d) {
    return d.val;
})]),

这里nested_data是一个具有values数组的对象数组。 因此,最大分钟将无法正常工作。

<强>修正:

您需要收集数组中的所有值并创建一个如下所示的数组:

//get the array of all values.
var arrays = nested_data.map(function (k) {
    return k.values
});
var collect = [].concat.apply([], arrays);

错误2:

未在代码中正确处理日期。

xScale = d3.scale.linear().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(nested_data, function(d) {
    return d.date;
}), d3.max(data, function(d) {
    return d.date;//this is a string d3 does not know its a date
})]),

<强>修正:

您需要将其转换为像这样的日期

var parseDate = d3.time.format("%m/%d/%Y").parse;
//get the array of all values.
var arrays = nested_data.map(function (k) {
    return k.values
});
var collect = [].concat.apply([], arrays);
//converting date
collect.forEach(function(d){d.date1 = parseDate(d.date)});

然后x轴最大最小值函数就像

xScale = d3.time.scale().range([MARGINS.left, WIDTH - MARGINS.right]).domain([d3.min(collect, function (d) {

    return d.date1;
}), d3.max(collect, function (d) {
    return d.date1;
})]),
yScale = d3.scale.linear().range([HEIGHT - MARGINS.top, MARGINS.bottom]).domain([d3.min(collect, function (d) {
    return d.val;
}), d3.max(collect, function (d) {
    return d.val;
})]),

完整的工作更正代码here

希望这有帮助!

答案 1 :(得分:1)

问题是,您已将错误的值设置为domainxScale的{​​{1}}。 要设置正确的域值,您应该更改数据结构,如下所示,并使用数据数组来设置域。

yScale

保持var data = [{"date":"09/04/2015","val":0,"status":false}, {"date":"09/05/2015","val":222,"status":false}, {"date":"09/06/2015","val":168,"status":false}, {"date":"09/07/2015","val":203,"status":false}, {"date":"09/08/2015","val":219,"status":false}, {"date":"09/09/2015","val":237,"status":false}, {"date":"09/10/2015","val":241,"status":false}, {"date":"09/11/2015","val":397,"status":false}, {"date":"09/12/2015","val":158,"status":false}, {"date":"09/13/2015","val":154,"status":false}, {"date":"09/14/2015","val":193,"status":false}, {"date":"09/15/2015","val":202,"status":false}, {"date":"09/16/2015","val":218,"status":false}, {"date":"09/17/2015","val":466,"status":false}, {"date":"09/18/2015","val":439,"status":false}, {"date":"09/19/2015","val":278,"status":false}, {"date":"09/20/2015","val":271,"status":false}, {"date":"09/21/2015","val":475,"status":false}, {"date":"09/22/2015","val":494,"status":false}, {"date":"09/23/2015","val":498,"status":false}, {"date":"09/24/2015","val":503,"status":false}, {"date":"09/25/2015","val":437,"status":false}, {"date":"09/26/2015","val":286,"status":false}, {"date":"09/27/2015","val":280,"status":false}, {"date":"09/28/2015","val":496,"status":false}, {"date":"09/29/2015","val":514,"status":false}, {"date":"09/05/2015","val":3170,"status":true}, {"date":"09/11/2015","val":8643,"status":true}, {"date":"09/04/2015","val":0,"status":true}, {"date":"09/08/2015","val":6146,"status":true}, {"date":"09/12/2015","val":2414,"status":true}, {"date":"09/14/2015","val":5711,"status":true}, {"date":"09/19/2015","val":4118,"status":true}, {"date":"09/26/2015","val":3990,"status":true}, {"date":"09/06/2015","val":2565,"status":true}, {"date":"09/09/2015","val":6426,"status":true}, {"date":"09/13/2015","val":2514,"status":true}, {"date":"09/15/2015","val":5690,"status":true}, {"date":"09/16/2015","val":6222,"status":true}, {"date":"09/17/2015","val":10858,"status":true}, {"date":"09/18/2015","val":9718,"status":true}, {"date":"09/20/2015","val":4006,"status":true}, {"date":"09/21/2015","val":11135,"status":true}, {"date":"09/23/2015","val":11264,"status":true}, {"date":"09/25/2015","val":8831,"status":true}, {"date":"09/27/2015","val":3984,"status":true}, {"date":"09/28/2015","val":11554,"status":true}, {"date":"09/07/2015","val":5562,"status":true}, {"date":"09/10/2015","val":6505,"status":true}, {"date":"09/22/2015","val":11405,"status":true}, {"date":"09/24/2015","val":11411,"status":true}, {"date":"09/29/2015","val":12086,"status":true}]; var nested_data = d3.nest() .key(function(d) { return d.status; }) .entries(data); var xScale = d3.scale.linear() .range([MARGINS.left, WIDTH - MARGINS.right]) .domain([d3.min(data, function(d) { return new Date(d.date); }), d3.max(data, function(d) { return new Date(d.date); })]), yScale = d3.scale.linear() .range([HEIGHT - MARGINS.top, MARGINS.bottom]) .domain([d3.min(data,function(d) { return d.val; }), d3.max(data, function(d) { return d.val; })]); 数组不变,并生成日期和值的总列表以设置查找域值。

nested_data
  

注意:也可以使用var allValues = nested_data.map(function(d){ return d.values }).reduce(function(a,b){ return d3.merge([a,b]); }); var xScale = d3.scale.linear() .range([MARGINS.left, WIDTH - MARGINS.right]) .domain([d3.min(allValues, function(d) { return new Date(d.date); }), d3.max(allValues, function(d) { return new Date(d.date); })]), yScale = d3.scale.linear() .range([HEIGHT - MARGINS.top, MARGINS.bottom]) .domain([d3.min(allValues,function(d) { return d.val; }), d3.max(allValues, function(d) { return d.val; })]); 代替d.date