使用更新功能重绘图形时出错

时间:2015-04-03 22:10:08

标签: d3.js

我正在尝试每次移动滑块时重绘和更新我的图形,这会将我的数据集过滤到该年份范围内。不幸的是,事情不能正常工作,我不确定我的错误在哪里。

当我尝试运行我的代码时,我收到此错误:

Error: Invalid value for <rect> attribute y="NaN"
Error: Invalid value for <rect> attribute height="NaN"

我完全迷失了,非常感谢任何帮助。

链接到我的小提琴:http://jsfiddle.net/vyab4kcf/11/

1 个答案:

答案 0 :(得分:3)

你不应该这样做......

request_data = data;

并且这一行指的是全局year何时应该是本地参数sexYear

    var yearData = data.filter(function (element) { return element.YEAR == year });

应该是

    var yearData = data.filter(function (element) { return element.YEAR == sexYear });

此外,请尝试change事件以及input,以便在IE中使用...

d3.select("#sexYear").on("change", function () {
    update(+this.value);
});
此处未定义

this.value,因为使用全局this上下文

调用更新
function update(sexYear) { 
    console.log(this.value);

你应该阅读这两行并思考他们在做什么......

    var ageNames = d3.keys(yearData[0]).filter(function (key) { return key !== "CAUSE"; });
    var ageNames = d3.keys(yearData[0]).filter(function (key) { return key !== "YEAR"; });

我保证不是你的想法。

ageNames是一个非常令人困惑的名称,例如它应该是seriesNames。然后你就可以这样实现......

var notSeriesNames = ['CAUSE', 'YEAR']
//...
var seriesNames = d3.keys(yearData[0]).filter(function (key) {
    return notSeriesNames.every(function (e, i, i) { return key != e })
});

最后,您需要修复UPDATE,ENTER,EXIT结构。这是一切固定的功能......

&#13;
&#13;
window.onload = function () {
	console.clear();
	var margin = { top: 10, right: 10, bottom: 35, left: 30 },
			width = 400 - margin.left - margin.right,
			height = 150 - margin.top - margin.bottom;

	var x0 = d3.scale.ordinal()
			.rangeRoundBands([0, width], 0.1);

	var x1 = d3.scale.ordinal();

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

	var color = d3.scale.ordinal()
			.range(["#FD8C25", "#99ABC4"]);

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

	var year = 1979;

	var yAxis = d3.svg.axis()
			.scale(y)
			.orient("left")
			.tickFormat(d3.format(".2s"));

	var svg = d3.select("body").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 + ")");

	var request_data = d3.csv("http://www.sfu.ca/~gdwang/Sex.csv", function (error, data) {

		d3.select("#sexYear").on("change", function () {
			update(+this.value);
		});

		d3.select("#sexYear").on("input", function () {
			update(+this.value);
		});
		update(year);

		// update the year
		function update(sexYear) {
			var notSeriesNames = ['CAUSE', 'YEAR', 'series']
			console.log('update ', sexYear);

			// adjust the text on the year slider
			d3.select("#sexYear-value").text(sexYear);
			d3.select("#sexYear").property("value", sexYear);

			var yearData = data.filter(function (element) { return element.YEAR == sexYear });

			var seriesNames = d3.keys(yearData[0]).filter(function (key) {
				return notSeriesNames.every(function (element, idnex, array) {
					return key != element
				})
			});

			yearData.forEach(function (d) {
				d.series = seriesNames.map(function (name) { return { name: name, value: +d[name] }; });
			});

			x0.domain(yearData.map(function (d) { return d.CAUSE; }));
			x1.domain(seriesNames).rangeRoundBands([0, x0.rangeBand()]);
			y.domain([0, d3.max(yearData, function (d) { return d3.max(d.series, function (d) { return d.value; }); })]);

			//Cause groups
			//UPDATE
			var causeUpdate = svg.selectAll(".CAUSE")
					 .data(yearData),
			//ENTER ****native d3 SIDE EFFECT**** enter selection is added to update selection 
					causeEnter = causeUpdate.enter().append("g")
					 .attr("class", "CAUSE")
					 .attr("transform", function (d) { return "translate(" + x0(d.CAUSE) + ",0)"; }),
			//EXIT
					causeExit = causeUpdate.exit().remove(),

		//Series groups
			//UPDATE
					seriesUpdate = causeUpdate.selectAll("rect")
					.data(function (d) {
						return d.series;
					});
			//ENTER ****native d3 SIDE EFFECT**** enter selection is added to update selection 
			seriesUpdate.enter().append("rect")
			//UPDATE + ENTER
			seriesUpdate.attr("width", x1.rangeBand())
			.style("fill", function (d) {
				return color(d.name);
			})
						.transition()
					.attr("x", function (d) {
						return x1(d.name);
					})
				.attr("y", function (d) {
					return y(d.value);
				})
				.attr("height", function (d) {
					return height - y(d.value);
				})
			//EXIT
			seriesUpdate.exit().remove()
		}

		//draw the bars
		svg.append("g")
				.attr("class", "x axis")
				.attr("transform", "translate(0," + height + ")")
				.call(xAxis)
				.selectAll('text')
					.attr('transform', 'rotate(-15)')
					.style('text-anchor', 'end');

		svg.append("g")
				.attr("class", "y axis")
				.call(yAxis)
				.append("text")
				.attr("transform", "rotate(-90)")
				.attr("y", 6)
				.attr("dy", ".71em")
				.style("text-anchor", "end")
				.text("Potential Years Lost");

		d3.selectAll(".tick > text")
		.style("font-size", 6);

	})
};
&#13;
body {
  font: 10px sans-serif;
}

.axis path,
.axis line {
  fill: none;
  stroke: #000;
  shape-rendering: crispEdges;
}

.bar {
  fill: steelblue;
}

.x.axis path {
  display: none;
}
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <label for="sexYear" style="display: inline-block; width: 200px; text-align: right">
        Year = <span id="sexYear-value">…</span>
    </label>
    <input type="range" min="1979" max="1999" id="sexYear">
&#13;
&#13;
&#13;