2017-02-20 221 views
0

我一直在构建d3条形图,但我坚持为什么我的折线图不会加载 - 抛出无法读取未定义d3错误的属性“长度”,所以我认为这是由于没有正确指出数据,但不确定。我正在使用的数据是:D3折线图 - 无法显示线条

var data = [ 
     {month: "May", emailsDelivered: 20000, emailsOpened: 10000, emailsClicked: 7900}, 
     {month: "Jun", emailsDelivered: 28000, emailsOpened: 11000, emailsClicked: 5900}, 
     {month: "Jul", emailsDelivered: 30000, emailsOpened: 15000, emailsClicked: 2900}, 
     {month: "Aug", emailsDelivered: 40000, emailsOpened: 8000, emailsClicked: 6900}, 
     {month: "Sep", emailsDelivered: 30000, emailsOpened: 10000, emailsClicked: 7900}, 
     {month: "Oct", emailsDelivered: 25000, emailsOpened: 10000, emailsClicked: 4900}, 
     {month: "Nov", emailsDelivered: 30000, emailsOpened: 9000, emailsClicked: 5900}, 
     {month: "Dec", emailsDelivered: 36000, emailsOpened: 2000, emailsClicked: 2900}, 
     {month: "Jan", emailsDelivered: 41000, emailsOpened: 5000, emailsClicked: 1900}, 
     {month: "Feb", emailsDelivered: 46000, emailsOpened: 7000, emailsClicked: 8900}, 
     {month: "Mar", emailsDelivered: 38000, emailsOpened: 16000, emailsClicked: 4900}, 
     {month: "Apr", emailsDelivered: 24000, emailsOpened: 10000, emailsClicked: 7900} 
    ] 

这里是我的代码的其余部分。这是我第一次发布在stackoverflow,所以我道歉,如果我的格式不好。

var margin = {top: 20, right: 80, bottom: 30, left: 50}, 
 
    width = 960 - margin.left - margin.right, 
 
    height = 500 - margin.top - margin.bottom; 
 

 
var xScale = d3.scale.ordinal() 
 
    .rangeRoundBands([0, width], 0.2); 
 

 
var yScale = d3.scale.linear() 
 
    .range([height, 0]); 
 

 
var xAxis = d3.svg.axis() 
 
    .scale(xScale) 
 
    .orient("bottom"); 
 

 
var yAxis = d3.svg.axis() 
 
    .scale(yScale) 
 
    .orient("left") 
 

 

 
var svg = d3.select("#emails_graph").append("svg") 
 
    .attr("width", width + margin.left + margin.right) 
 
    .attr("height", height + margin.top + margin.bottom) 
 
    .append("g") 
 
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")"); 
 

 
xScale.domain(data.map(function(d) { return d.month; })); 
 
yScale.domain([0, d3.max(data, function(d) { return d.emailsDelivered; })]); 
 

 

 
var line = d3.svg.line() 
 
     .x(function(d, i) { return (xScale(i) + xScale.rangeBand()/2); }) 
 
     .y(function(d){ return yScale(d); }); 
 

 
var lines = svg.selectAll("path.line") 
 
     .data(data) 
 
     .enter() 
 
     .append("path") 
 
      .attr("d", line(data.emailsDelivered)) 
 
      .attr("class", "line") 
 
      .attr("fill", "none") 
 
      .attr("stroke", "#888");

+0

可以为您的HTML代码添加到下一个片段? – niceman

+0

这主要是D3 API的错误用法,我并不是D3的专家,但可能值得检查'.data'的文档,也许它需要不同的线形图(可能是数组数组) – niceman

回答

2

有几个问题回事。

首先,这里是你的代码工作jsfiddle。 https://jsfiddle.net/28w8kk3u/

  1. 你的目的就是让这个变量data包含点单行线,但是当你调用.data(data),D3看到有12个独立的对象的数组。您需要致电.data([data])。这样,d3就会看到一个单个“对象”的数组,在那个单个对象中有12个数据点。

  2. d3.svg.line()创建的线条生成器需要被告知如何从传入的对象中检索您想要的x和y值。你试图通过

.x(function(d, i) { return (xScale(i) + xScale.rangeBand()/2); })

为你的X-访问功能。这对d3没有任何意义,因为你创建了一个ordinal比例尺,它将字符串映射到数字(例如,将'Jan'放入xScale并返回40)。该xScale期待您的月份名称,因此

.x(function(d) { return (xScale(d.month)); })

线发生器:

var line = d3.svg.line() 
    .x(function(d) { return (xScale(d.month)); }) 
    .y(function(d){ return yScale(d.emailsDelivered); }); 

然后,致电线发生器,你需要在整个对象传递。

.attr("d", line) 

以上是简写

.attr("d",function(d){ 
    return line(d) 
}) 
+0

非常感谢!!!!!效果很好,并帮助我了解我侧身走到哪里。再次感谢一百万次。 – JayRedTwo