我在这里看到了一个如何绘制折线图的例子。我试图从"修复任意数据集"部分复制他们的示例,但我无法使其发挥作用。
希望有人能向我解释我做错了什么。
这是我使用的代码:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<script src="js/d3.min.js" charset="utf-8"></script>
<script src="js/jquery-1.11.2.min.js" charset="utf-8"></script>
<style>
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
.line {
fill: none;
stroke: steelblue;
stroke-width: 1.5px;
}
</style>
</head>
<body>
<table class="small-chart">
<tr>
<td id="chart_str"></td>
</tr>
</table>
</body>
<script>
var margin = {top: 20, right: 30, left: 30, bottom: 20}
height = 300 - margin.top - margin.bottom,
width = 300 - margin.left - margin.right;
var data = [{"x":100, "y":0}, {"x":110, "y":10}, {"x":120, "y":20}, {"x":130, "y":30}]
var x = d3.scale.linear()
.domain(d3.extent(data, function (d) { return d.x; }))
.range([0, width]);
var y = d3.scale.linear()
.domain(d3.extent(data, function (d) { return d.y; }))
.range([height, 0]);
var lineFunction = d3.svg.line()
.x(x, function (d) { return d.x; })
.y(y, function (d) { return d.y; });
var svg = d3.select('#chart_str').append('svg')
svg.append('path')
.attr('class', 'line')
.transition()
.duration(3000)
.attrTween('d', getSmoothInterpolation(data));
function getSmoothInterpolation(iData) {
return function (d, i, a) {
var interpolate = d3.scale.linear()
.domain([0, 1])
.range([1, iData.length + 1]);
return function(t) {
var flooredX = Math.floor(interpolate(t));
var weight = interpolate(t) - flooredX;
var interpolatedLine = iData.slice(0, flooredX);
if(flooredX > 0 && flooredX < 31) {
var weightedLineAverage = iData[flooredX].y * weight + iData[flooredX-1].y * (1-weight);
interpolatedLine.push({"x":interpolate(t)-1, "y":weightedLineAverage});
}
return lineFunction(interpolatedLine);
}
}
}
</script>
我在控制台中不断收到以下错误:
Error: Problem parsing d="MNaN,NaNLNaN,NaN" test_line.html:1
Error: Problem parsing d="MNaN,NaNLNaN,NaNLNaN,NaN" test_line.html:1
Error: Problem parsing d="MNaN,NaNLNaN,NaNLNaN,NaNLNaN,NaN" test_line.html:1
Uncaught TypeError: Cannot read property 'y' of undefined test_line.html:91
这是一把小提琴:http://jsfiddle.net/henbox/t3fam08j/1/.请注意,我添加了一些额外的数据点,以便更容易地了解发生了什么
根据@user1614080的评论,在进入过渡\插值位之前,先绘制基本折线图。
为此,您需要确保将x
和y
比例应用于lineFunction
中的点,因此更改:
var lineFunction = d3.svg.line()
.x(x, function (d) { return d.x; })
.y(y, function (d) { return d.y; });
至
var lineFunction = d3.svg.line()
.x(function (d) { return x(d.x); })
.y(function (d) { return y(d.y); });
还要定义svg的宽度和高度,以确保线条适合:
.append('svg')
.attr("width", width)
.attr("height", height)
...
错误:"Uncaught TypeError:无法读取undefined的属性'y'"源于flooredX可以大于iData+1中的元素数,因此iData[flooredX]
不存在,iData[flooredX].y
是undefined
。
插值函数有一条奇怪的"if (flooredX > 0 && flooredX < 31)
"线,其中31
是硬编码的(我不能确切地说为什么,我认为xample中的数据正好有30个点)。如果你用iData.length
替换31
,你就会处理这种情况:
if (flooredX > 0 && flooredX < iData.length) {
...
}
您需要做的最后一个更改是将点推送到interpolatedLine
数组。在您当前的代码中,您有:
interpolatedLine.push({
"x": interpolate(t) - 1,
...
这将在0和iData.length
之间推送x
值(即数据中x/y值对的计数),而不是您实际想要传递的值(x
在100和160之间)
我认为,对于您链接到的示例,假设原始数据中的x
值将从0开始并运行到30:这对您的示例没有太大帮助。绕过这一问题的一种方法是对需要从x
值1, 2, 3...
到110, 120, 130...
的转换进行硬编码,因此更改:
"x": interpolate(t) - 1,
至
"x": 10* (interpolate(t) - 1) + 100,
这不是一种很好的方式,因为它很难编码关于x值的假设。我相信有更好的方法