【问题标题】:D3.js Cannot read property 'length' of undefinedD3.js 无法读取未定义的属性“长度”
【发布时间】:2016-03-10 12:41:43
【问题描述】:

我对 d3.js 和网络也很陌生。我想使用 csv 文件来绘制折线图,​​但我遇到了一些我无法真正修复的错误:

代码如下:

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 的一部分,非常基本,所以我不明白为什么它不起作用。

庇护、来源、年份、月份、价值

德国,阿富汗,2014 年 1 月,981 德国,阿富汗,2014,2月,781 德国,阿富汗,2014,3月,675 德国,阿富汗,2014,4月,673 德国,阿富汗,2014,5月,523 德国,阿富汗,2014,621 德国,阿富汗,2014,7月,752 德国,阿富汗,2014,8月,743 德国,阿富汗,2014年9月,922

我认为这是一个非常愚蠢的错误,你能帮帮我吗?

【问题讨论】:

  • 您是否在调试代码并知道在哪一行出现错误?
  • 控制台在第 93 行或第 94 行说了什么

标签: javascript csv d3.js


【解决方案1】:

您的错误是假设调用 d3.csv(...) 会返回您的 CSV 数据。

d3.csv 进行 AJAX 调用以加载您的数据,然后在加载该数据时调用回调函数。当数据在后台加载时,您的代码会继续运行。当您编写 var data = [d3.csv(...)] 时,data 不包含从您的 CSV 文件加载的数据,它仅包含一个 d3 对象,您无法绘制它。

相反,您对d3.csv 的调用应如下所示:

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 将调用该函数来绘制图表。

我创建了一个render 函数,其中包含从var w = 800; 行到以var y = ... 开头的行的代码内容,然后是plot 函数的内容。我还用svg.selectAll替换了this.selectAll,并去掉了plot.call的使用。我写的render函数最终如下:

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();
}

进行这些更改后,我可以看到您的图表正常工作。

【讨论】:

  • 谢谢,它成功了。除了 d3.keys 之外是否还有一些过滤 csv 的条目?我想过滤原产国,例如阿富汗和叙利亚,用于交互目的。换句话说,我想将鼠标悬停在点上以获得原产国。 This is the source了解真实数据
  • @basedian:如果你有一个单独的问题,要做的就是问一个单独的问题。这是我看到的you have now done
猜你喜欢
  • 1970-01-01
  • 2016-11-27
  • 2017-12-08
  • 1970-01-01
  • 2016-03-25
  • 1970-01-01
  • 2011-11-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多