D3.js无法读取未定义的属性"length" [英] D3.js Cannot read property 'length' of undefined
问题描述
我对d3.js和网络还很陌生.我想使用一个csv文件来绘制折线图,但出现了一些我无法真正解决的错误:
I'm pretty new to d3.js and to web too. I wanted to ue a csv file to plot a line graph but I got some errors I can't really fix:
这是代码:
body,html{
margin: 0;
padding: 0;
font-family: "Arial", sans-serif;
font-size: 0.95em;
text-align: center;
}
#chart{
background-color: #F5F2EB;
border: 1px solid #CCC;
}
.bar{
fill: purple;
shape-rendering: crispEdges;
}
.bar-label{
fill: black;
text-anchor: middle;
font-size: 18px;
}
.axis path,
.axis line{
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.gridline path,
.gridline line{
fill: none;
stroke: #ccc;
shape-rendering: crispEdges;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Learning D3</title>
<link rel="stylesheet" href="main.css">
<script type="text/javascript" src="d3.min.js"></script>
</head>
<body>
<!--Place all DOM elements here -->
<script>
var data= [
d3.csv("refugee_data.csv", function(d) {
return {
/*year: new Date(+d.Year, 0, 1), // convert "Year" column to Date
make: d.Make,
model: d.Model,
length: +d.Length // convert "Length" column to number*/
date: d.Year + "/" +d.Month,
origin: d.Origin,
asylum: d.Asylum,
value: +d.Value
};
}, function(error, rows) {
console.log(rows);
})
];
var w = 800;
var h = 450;
var margin = {
top: 58,
bottom: 100,
left: 80,
right: 40
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("id", "chart")
.attr("width", w)
.attr("height", h);
var dateParser = d3.time.format("%Y/%B").parse;
var x = d3.time.scale()
.domain(d3.extent(data, function(d){
var date = dateParser(d.date);
return date;
}))
.range([0,width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d){
return d.value;
})])
.range([height,0]);
function plot(params){
//enter()
this.selectAll(".point")
.data(params.data)
.enter()
.append("circle")
.classed("point", true)
.attr("r", 2);
//Update
this.selectAll(".point")
.attr("cx", function(d){
var date = dateParser(d.date);
return x(date);
})
.attr("cy", function(d){
return y(d.value);
})
//Exit()
this.selectAll(".point")
.data(params.data)
.exit()
.remove();
}
plot.call(chart, {
data: data
})
</script>
</body>
</html>
这是我的csv的一部分,非常基本,所以我不明白为什么它不起作用.
And this ist my a part of my csv, pretty basic so I don't get why it does not work.
避难所,产地,年,月,值
Asylum,Origin,Year,Month,Value
德国,阿富汗,2014年1月,981年 德国,阿富汗,2014年2月,781 德国,阿富汗,2014年3月,675 德国,阿富汗,2014年4月673日 德国,阿富汗,2014年5月,523 德国,阿富汗,2014年6月,621 德国,阿富汗,2014年,752年7月 德国,阿富汗,2014年8月,743 德国,阿富汗,2014年,922年9月
Germany,Afghanistan,2014,January,981 Germany,Afghanistan,2014,February,781 Germany,Afghanistan,2014,March,675 Germany,Afghanistan,2014,April,673 Germany,Afghanistan,2014,May,523 Germany,Afghanistan,2014,June,621 Germany,Afghanistan,2014,July,752 Germany,Afghanistan,2014,August,743 Germany,Afghanistan,2014,September,922
我认为这是一个非常愚蠢的错误,您能帮我吗?
I assume it is a really stupid mistake can you please help me out?
推荐答案
您的错误是假设调用d3.csv(...)
返回了您的CSV数据.
Your mistake is assuming that calling d3.csv(...)
returns your CSV data.
d3.csv
进行AJAX调用以加载您的数据,然后在该数据已加载时调用一个回调函数.您的代码在后台加载数据的同时继续运行.编写var data = [d3.csv(...)]
时,data
不包含从CSV文件加载的数据,它仅包含d3对象,并且无法绘制该对象.
d3.csv
makes an AJAX call to load your data and then calls a callback function when that data has been loaded. Your code continues running while the data loads in the background. When you write var data = [d3.csv(...)]
, data
doesn't contain the data loaded from your CSV file, it contains only a d3 object, and you cannot plot that.
相反,您对d3.csv
的调用应类似于以下内容:
Instead, your call to d3.csv
should look something like the following:
d3.csv("refugee_data.csv", function(d) {
return {
date: d.Year + "/" +d.Month,
origin: d.Origin,
asylum: d.Asylum,
value: +d.Value
};
}, function(error, rows) {
console.log(rows);
render(rows);
});
其中render
是函数,当数据加载完成后,d3会调用该函数绘制图形.
where render
is a function that d3 will call to draw your graph when the data has finished loading.
我创建了一个render
函数,该函数包含从var w = 800;
行到var y = ...
开头的行的代码内容,然后是plot
函数的内容.我还用svg.selectAll
替换了this.selectAll
,并删除了plot.call
的使用.我写的render
函数最终如下:
I created a render
function that contained the contents of your code from the line var w = 800;
to the lines beginning var y = ...
, followed by the contents of the plot
function. I also replaced this.selectAll
with svg.selectAll
, and remove the use of plot.call
. The render
function I wrote ended up as follows:
function render(data) {
var w = 800;
var h = 450;
var margin = {
top: 58,
bottom: 100,
left: 80,
right: 40
};
var width = w - margin.left - margin.right;
var height = h - margin.top - margin.bottom;
var svg = d3.select("body").append("svg")
.attr("id", "chart")
.attr("width", w)
.attr("height", h);
var dateParser = d3.time.format("%Y/%B").parse;
var x = d3.time.scale()
.domain(d3.extent(data, function(d){
var date = dateParser(d.date);
return date;
}))
.range([0,width]);
var y = d3.scale.linear()
.domain([0, d3.max(data, function(d){
return d.value;
})])
.range([height,0]);
//enter()
svg.selectAll(".point")
.data(data)
.enter()
.append("circle")
.classed("point", true)
.attr("r", 2);
//Update
svg.selectAll(".point")
.attr("cx", function(d){
var date = dateParser(d.date);
return x(date);
})
.attr("cy", function(d){
return y(d.value);
})
//Exit()
svg.selectAll(".point")
.data(data)
.exit()
.remove();
}
进行了这些更改之后,我能够看到您的图形工作正常.
After making these changes I was able to see your graph working.
这篇关于D3.js无法读取未定义的属性"length"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!