“Web 交互式数据可视化”第 11 章介绍了如何使用 D3.js 库创建堆叠条形图。该示例生成一个颠倒的图表,其中的条形图附在 x 轴的顶部。
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript">
var w = 500;
var h = 300;
var dataset = [[ { x: 0, y: 5 }, { x: 1, y: 4 }, { x: 2, y: 2 }, { x: 3, y: 7 }, { x: 4, y: 23 }],
[ { x: 0, y: 10 }, { x: 1, y: 12 }, { x: 2, y: 19 }, { x: 3, y: 23 }, { x: 4, y: 17 } ],
[ { x: 0, y: 22 }, { x: 1, y: 28 }, { x: 2, y: 32 }, { x: 3, y: 35 }, { x: 4, y: 43 } ]];
var stack = d3.layout.stack();
stack(dataset);
var xScale = d3.scale.ordinal()
.domain(d3.range(dataset[0].length)).rangeRoundBands([0, w], 0.05);
var yScale = d3.scale.linear()
.domain([0, d3.max(dataset, function(d) {
return d3.max(d, function(d) { return d.y0 + d.y; });
})])
.range([0, h]);
var colors = d3.scale.category10();
var svg = d3.select("body").append("svg").attr("width", w).attr("height", h);
var groups = svg.selectAll("g").data(dataset).enter().append("g")
.style("fill", function(d, i) { return colors(i); });
var rects = groups.selectAll("rect")
.data(function(d) { return d; })
.enter()
.append("rect")
.attr("x", function(d, i) { return xScale(i); })
.attr("y", function(d) { return yScale(d.y0); })
.attr("height", function(d) { return yScale(d.y); })
.attr("width", xScale.rangeBand());
</script>
这是使堆叠栏上下颠倒的代码。
当我更改如下几个代码时:
1) 更改 yScale 范围:
.range([0, h]);
至
.range([h, 0]);
2)更改矩形“y”.attr:
.attr("y", function(d) { return yScale(d.y0); })
至
.attr("y", function(d) { return yScale(d.y0) + yScale(d.y) - h; })
3)更改矩形“高度”.attr:
.attr("height", function(d) { return yScale(d.y); })
至
.attr("height", function(d) { return h - yScale(d.y); })
应用这些更改后,堆栈会附着到底部并仍然保持其相对大小。 right graph
问题是,我不明白第二步和第三步的含义。
为什么y
应该是yScale(d.y0) + yScale(d.y) - h
,
为什么高度
应该是h - yScale(d.y)
?
如果将这些值修改为不同的值(例如y
为(yScale(d.y0) + yScale(d.y))/10
左右),需要图表未显示。
最佳答案
这种“逆向数学”的原因(正如 Scott Murray 在他的代码中所说)是,在你的第一个代码中,颠倒的代码,SVG 坐标系和范围都有从上到下增长的 Y 坐标(零位于顶部,最大值位于底部)。但是,当您在第二个代码中将范围反转为 ([h, 0])
时,SVG 坐标系继续使 Y 坐标从上到下增长,尽管范围现在正在上升。
在“颠倒”代码中,条形的顶部实际上是其底部,并且其高度随着 SVG 系统而下降。但在第二个代码(“正常”图表)中,事情变得更加复杂:条形的“基数”不再是其“y”属性,并且高度值向下添加像素,无论反转范围如何。 SVG 的坐标系不会仅仅因为我们反转了范围而自动反转。
这很复杂,所以让我重新表述一下:在 SVG 坐标系中,“y”属性始终是矩形的顶部。在您的第一个代码中,矩形的顶部是栏的底部...但是,在您的第二个代码中,矩形的顶部是栏的顶部。我知道这很令人困惑。
让我们做一个简单的数学计算:想象一个高度为 100 像素的 SVG 和一个高度为 80 像素的条形 (y0: 0, y:80)。要绘制此条形,“y”属性必须设置其顶部。如何计算呢? yScale(d.y0)
给我们 100,yScale(d.y)
给我们 20。通过将它们相加,我们得到 120,减去 100(高度)得到 20 ,顶部的位置。为什么不直接直接使用d.y
呢?它可以适用于第一个柱,但不适用于后续柱。
现在是高度,必须是 80 像素。 yScale(d.y)
给我们 20,因此,100(高度)减去 20 给我们 80...这适用于每个条。
关于javascript - 如何使用 d3.js 制作正确的倒置堆叠图?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38196412/