我有单独的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()
返回的函数显然没有正确的形式。怎么了?我祈祷不是一个错字!
答案 0 :(得分:6)
我知道已经有一年多了,但我也不得不处理这个问题。
将路径数据(x,y)存储在2个单独的数组中比2D数组d3.svg.line
期望的内存效率高得多。对于非常多的点,通过循环遍历所有元素来创建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))
查看更新的小提琴here
答案 1 :(得分:3)
根据Elijah关于d3.svg.line
的评论,我认为如果没有按照此功能的预期放置数组,我很难做到这一点。所以:
var xy = [];
for(var i=0;i<xdata.length;i++){
xy.push({x:xdata[i],y:ydata[i]});
}
我对.domain
和slice
功能本身做了其他更改。这是一个FIDDLE,其结果是我的努力。
答案 2 :(得分:1)
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]);})
然后将你的行函数指向newData,你应该设置:
svg.append("path")
.attr("class", "line")
.attr("d", slice(newData))
但是,通常,你最好建立一个坐标对数组,因为这是它所期望的。