使用分离的、固定的x和y输入数组在d3.js中绘制线条

3
我有独立的x和y数组,想要使用线路路径连接这些点。这似乎是最简单的例子之一,但我不太理解如何编写该函数。这是我的代码:
<!DOCTYPE html>
<meta charset="utf-8">

<body>
<script src = "http://d3js.org/d3.v3.min.js"> </script>
<script>

var margin = {top: 20, right: 20, bottom: 20, left: 20},
    width = 600 - margin.left - margin.right,
    height = 270 - margin.top - margin.bottom;

var xdata = d3.range(20);
var ydata = [1, 4, 5, 9, 10, 14, 15, 15, 11, 10, 5, 5, 4, 8, 7, 5, 5, 5, 8, 10];

var xscl = d3.scale.linear()
    .domain(d3.extent(xdata))
    .range([0, width])

var yscl = d3.scale.linear()
    .domain(d3.extent(ydata))
    .range([height, 0])

var slice = d3.svg.line()
    .x(function(d) { return xscl(xdata[d]);})
    .y(function(d) { return yscl(ydata[d]);})

var svg = d3.select("body")
    .append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)

svg.append("path")
    .attr("class", "line")
    .attr("d", slice)

</script>
</body>
但是它返回了一个错误Uncaught TypeError: Cannot read property 'length' of undefined,因此由d3.svg.line()返回的函数形式不正确。问题在哪里?我祈求不是拼写错误!
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
7
我知道已经过去一年多了,但我也不得不处理这个问题。 将路径数据(x,y)存储在两个独立的数组中比2D数组期望的更节省内存。对于大量点的情况,接受的答案通过循环遍历所有元素来创建2D数组也是低效的。 我找到的解决方案是编写一个包装函数d3.svg.line,如下所示:
var line = function(x, y){
    return d3.svg.line()
    .x(function(d,i) { return x[i]; }) 
    .y(function(d,i) { return y[i]; })
    (Array(x.length));
}

然后设置路径属性:

svg.append("path")
    .attr("d", line(x_array, y_array))

请查看更新后的演示这里


4

基于Elijah关于d3.svg.line的正确评论,我认为如果不将数组按照该函数的预期格式传入,这将很难进行。因此:

var xy = [];
for(var i=0;i<xdata.length;i++){
   xy.push({x:xdata[i],y:ydata[i]});
}

我对.domainslice函数本身进行了其他更改。这里是我努力的结果的FIDDLE


谢谢。我从d3.svg.line函数中删除了i。我来自于R,而JS的数据结构让我很头疼。它们很难阅读,似乎过于复杂。我猜d3.js经常需要以这种特定格式呈现数据,这很好,但我还没有找到文档在哪里。我可能错过了它,或者它被假定为已知,这对新手来说很困难。非常感谢,我在这里学到了非常有用的东西。 - Bryan Hanson
1
YMW。D3有它自己的一些挑战...但我们都喜欢它 :) - FernOfTheAndes
1
我将最终版本放在gist上,并添加了注释。这可能有助于那些正在学习d3思维方式的人。 - Bryan Hanson

2

d3.svg.line只能处理一个数据源。然而,您可以将两个数据源放入对象中并提供给它:

newData = {x: xdata, y: ydata};

 var slice = d3.svg.line()
  .x(function(d,i) { return xscl(d.xdata[i]);})
  .y(function(d,i) { return yscl(d.ydata[i]);})

然后将你的line函数指向newData,你就可以了:

 svg.append("path")
  .attr("class", "line")
  .attr("d", slice(newData))

通常,你最好构建一个坐标对数组,因为这是它所期望的。


你介意看一下这个 fiddle 吗?路径已经被创建,但没有数据点。 - Bryan Hanson
看起来 slice(xy)null - Bryan Hanson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,