好吧,假设您有一个数字数组作为数据集,其中包括一些正值和负值:
var data = [-15, -20, -22, -18, 2, 6, -26, -18];
您需要两个比例来构建条形图。您需要一个定量量表(通常是线性标尺 https://github.com/mbostock/d3/wiki/Quantitative-Scales#wiki-linear)来计算沿x- 轴,和第二个序数尺度 https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal计算沿y-axis.
对于定量尺度,您通常需要计算数据的域,该域基于最小值和最大值。一个简单的方法是通过d3.范围 https://github.com/mbostock/d3/wiki/Arrays#wiki-d3_extent:
var x = d3.scale.linear()
.domain(d3.extent(data))
.range([0, width]);
您可能还想nice https://github.com/mbostock/d3/wiki/Quantitative-Scales#wiki-linear_nice比例尺稍微变圆。另一个例子,有时您希望零值位于画布的中间,在这种情况下,您需要取最小值和最大值中的较大者:
var x0 = Math.max(-d3.min(data), d3.max(data));
var x = d3.scale.linear()
.domain([-x0, x0])
.range([0, width])
.nice();
或者,您可以对您想要的任何域进行硬编码。
var x = d3.scale.linear()
.domain([-30, 30])
.range([0, width]);
For the y-axis,你会想要使用范围圆带 https://github.com/mbostock/d3/wiki/Ordinal-Scales#wiki-ordinal_rangeRoundBands将垂直空间划分为每个条形的带。这还允许您指定条之间的填充量。通常,序数尺度与一些识别数据一起使用,例如名称或唯一 ID。但是,您也可以将序数尺度与数据索引结合使用:
var y = d3.scale.ordinal()
.domain(d3.range(data.length))
.rangeRoundBands([0, height], .2);
现在您已经有了两个比例,您可以创建 rect 元素来显示条形。一个棘手的部分是,在 SVG 中,矩形是定位的(x
and y
属性)基于其左上角。所以我们需要使用x- and y-缩放以计算左上角的位置,这取决于关联值是正数还是负数:如果该值为正数,则数据值确定条形的右边缘,而如果为负数,则数据值决定条形的右边缘。确定条的左边缘。因此这里的条件:
svg.selectAll(".bar")
.data(data)
.enter().append("rect")
.attr("class", "bar")
.attr("x", function(d, i) { return x(Math.min(0, d)); })
.attr("y", function(d, i) { return y(i); })
.attr("width", function(d, i) { return Math.abs(x(d) - x(0)); })
.attr("height", y.rangeBand());
最后,您可以添加一个轴以在顶部显示刻度线。您还可以计算填充样式(甚至渐变)来改变正值和负值的外观差异。把它们放在一起:
- 具有负值的条形图 http://bl.ocks.org/2368837