请参考以下链接:
https://bl.ocks.org/mbostock/34f08d5e11952a80609169b7917d4172
在这里数据是有序的(按顺序排列),如jan 2000,feb 2000等,但我想让d3图在jan 2001,feb 2000等无序数据上起作用。这可能吗?
最佳答案
简短的回答:不。
行生成器或区域生成器(该块中的那个)将根据输入数据的顺序生成一条线(或一个区域)。 API明确指出:
d3.line()
:为给定的数据数组生成一行。根据此线生成器的相关曲线,在将给定的输入数据传递到线生成器之前,可能需要按x值对其进行排序。 (强调我的)
让我们在一个基本示例中看到这一点。我有一组值和年份,其中的年份未排序:
var data = [{
year: 2010,
value: 100
}, {
year: 2017,
value: 70
}, {
year: 2012,
value: 50
}, {
year: 2016,
value: 10
}, {
year: 2013,
value: 90
}, {
year: 2014,
value: 20
}, {
year: 2011,
value: 50
}, {
year: 2015,
value: 40
}];
如果我以现在的方式将数据传递给线生成器,则这是折线图:
var svg = d3.select("svg");
var data = [{
year: 2010,
value: 100
}, {
year: 2017,
value: 70
}, {
year: 2012,
value: 50
}, {
year: 2016,
value: 10
}, {
year: 2013,
value: 90
}, {
year: 2014,
value: 20
}, {
year: 2011,
value: 50
}, {
year: 2015,
value: 40
}];
var parseTime = d3.timeParse("%Y");
data.forEach(function(d) {
d.year = parseTime(d.year)
});
var xScale = d3.scaleTime()
.domain(d3.extent(data, function(d) {
return d.year
}))
.range([0, 300]);
var yScale = d3.scaleLinear()
.domain(d3.extent(data, function(d) {
return d.value
}))
.range([150, 0]);
var lineGenerator = d3.line()
.x(function(d) {
return xScale(d.year)
})
.y(function(d) {
return yScale(d.value)
})
.curve(d3.curveMonotoneX)
svg.append("path")
.style("fill", "none")
.style("stroke", "teal")
.style("stroke-width", "2px")
.attr("d", lineGenerator(data));
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>
现在相同的代码,但是对数据进行排序:
data.sort(function(a, b) {
return d3.ascending(a.year, b.year)
});
结果如下:
var svg = d3.select("svg");
var data = [{
year: 2010,
value: 100
}, {
year: 2017,
value: 70
}, {
year: 2012,
value: 50
}, {
year: 2011,
value: 10
}, {
year: 2013,
value: 90
}, {
year: 2014,
value: 20
}, {
year: 2016,
value: 50
}, {
year: 2015,
value: 40
}];
var parseTime = d3.timeParse("%Y");
data.forEach(function(d) {
d.year = parseTime(d.year)
});
data.sort(function(a, b) {
return d3.ascending(a.year, b.year)
})
var xScale = d3.scaleTime()
.domain(d3.extent(data, function(d) {
return d.year
}))
.range([0, 300]);
var yScale = d3.scaleLinear()
.domain(d3.extent(data, function(d) {
return d.value
}))
.range([150, 0]);
var lineGenerator = d3.line()
.x(function(d) {
return xScale(d.year)
})
.y(function(d) {
return yScale(d.value)
})
.curve(d3.curveMonotoneX)
svg.append("path")
.style("fill", "none")
.style("stroke", "teal")
.style("stroke-width", "2px")
.attr("d", lineGenerator(data));
<script src="https://d3js.org/d3.v4.min.js"></script>
<svg></svg>