我注意到从 d3 版本 4 更新到版本 5 时行为发生了变化。在 v4 中,当数据集包含 y 轴的所有零值时,“0”刻度线会正确对齐到图表底部。
<head>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v4.min.js"></script>
<style>
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
</style>
</head>
<script>
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
var n = 21;
// An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
// var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } })
var dataset = d3.range(n).map(function(d) {
return {
"y": 0
}
})
var xScale = d3.scaleLinear()
.domain([0, n - 1])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d => d.y)])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) {
return xScale(i);
})
.y(function(d) {
return yScale(d.y);
})
.curve(d3.curveMonotoneX)
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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
</script>Run Code Online (Sandbox Code Playgroud)
对于我的用例,这是预期的行为。
在v5中,在相同条件下,“0”与y轴中心对齐。
<head>
<!-- load the d3.js library -->
<script src="https://d3js.org/d3.v5.min.js"></script>
<style>
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
</style>
</head>
<script>
var margin = {top: 50, right: 50, bottom: 50, left: 50}
, width = window.innerWidth - margin.left - margin.right
, height = window.innerHeight - margin.top - margin.bottom;
var n = 21;
// An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
// var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } })
var dataset = d3.range(n).map(function(d) { return {"y": 0 } })
var xScale = d3.scaleLinear()
.domain([0, n-1])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d => d.y)])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) { return xScale(i); })
.y(function(d) { return yScale(d.y); })
.curve(d3.curveMonotoneX)
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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
</script>Run Code Online (Sandbox Code Playgroud)
这两个示例之间的唯一区别是加载的 d3 版本。
有什么方法可以在 d3 的当前版本(v5)中保留 v4 中表现出的相同行为吗?
这不是D3 v4 和 v5 之间的区别。实际上,这个变化是在 D3 v5.8 中引入的。
看一下这里,这是使用 D3 v5.7 的代码:
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.js"></script>
<style>
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
</style>
</head>
<script>
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
var n = 21;
// An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
// var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } })
var dataset = d3.range(n).map(function(d) {
return {
"y": 0
}
})
var xScale = d3.scaleLinear()
.domain([0, n - 1])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d => d.y)])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) {
return xScale(i);
})
.y(function(d) {
return yScale(d.y);
})
.curve(d3.curveMonotoneX)
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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
</script>Run Code Online (Sandbox Code Playgroud)
现在使用 D3 v5.8 的相同代码:
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.8.0/d3.js"></script>
<style>
.line {
fill: none;
stroke: steelblue;
stroke-width: 2px;
}
</style>
</head>
<script>
var margin = {
top: 50,
right: 50,
bottom: 50,
left: 50
},
width = window.innerWidth - margin.left - margin.right,
height = window.innerHeight - margin.top - margin.bottom;
var n = 21;
// An array of objects of length N. Each object has key -> value pair, the key being "y" and the value is a random number
// var dataset = d3.range(n).map(function(d) { return {"y": d3.randomUniform(1)() } })
var dataset = d3.range(n).map(function(d) {
return {
"y": 0
}
})
var xScale = d3.scaleLinear()
.domain([0, n - 1])
.range([0, width]);
var yScale = d3.scaleLinear()
.domain([0, d3.max(dataset, d => d.y)])
.range([height, 0]);
var line = d3.line()
.x(function(d, i) {
return xScale(i);
})
.y(function(d) {
return yScale(d.y);
})
.curve(d3.curveMonotoneX)
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 + ")");
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(xScale));
svg.append("g")
.attr("class", "y axis")
.call(d3.axisLeft(yScale));
svg.append("path")
.datum(dataset)
.attr("class", "line")
.attr("d", line);
</script>Run Code Online (Sandbox Code Playgroud)
可以在 D3 v5.8 的发行说明中找到说明:
D3 规模:
对于折叠域,请使用域或范围的中点而不是start。(强调我的)
因此,恐怕您无能为力,除非回到 D3 v5.7 或更低版本。
事实上,D3 v5.8 与 v5.7 非常不同(并且不向后兼容,例如,请参阅新的比例构造函数,或新方法join),以我的愚见,它应该被命名为 D3 v6.0(当然,在语义版本控制之后,它仍然被命名为 v5,因为没有重大更改)。可以说,从 v5.7 到 v5.8 的差异比从 v4 到 v5 的差异更多。