d3.js - 具有负值的条形图

标签 d3.js

我需要创建一个可以有负值的 d3 条形图。理想情况下,零轴位置应根据数据的范围来计算,但我会选择一个假设对称正负范围的解决方案,即它始终位于图表的中间。

这是我想要实现的目标的示例。

Bar chart with negative values

最佳答案

好吧,假设您有一个数字数组作为数据集,其中包括一些正值和负值:

var data = [-15, -20, -22, -18, 2, 6, -26, -18];

您需要两个刻度来构建条形图。您需要一个定量刻度(通常为 linear scale )来计算沿 x 轴的条形位置,以及第二个 ordinal scale 。计算沿 y 轴的条形位置。

对于定量尺度,您通常需要计算数据的域,该域基于最小值和最大值。一个简单的方法是通过 d3.extent :

var x = d3.scale.linear()
    .domain(d3.extent(data))
    .range([0, width]);

您可能还想nice将比例尺稍微舍入。另一个例子,有时您希望零值位于 Canvas 的中间,在这种情况下,您需要取最小值和最大值中的较大者:

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]);

对于 y 轴,您需要使用 rangeRoundBands将垂直空间划分为每个条形的带。这还允许您指定条之间的填充量。通常,序数尺度与一些识别数据一起使用,例如名称或唯一 ID。但是,您也可以将序数尺度与数据索引结合使用:

var y = d3.scale.ordinal()
    .domain(d3.range(data.length))
    .rangeRoundBands([0, height], .2);

现在您已经有了两个比例,您可以创建 rect 元素来显示条形。一个棘手的部分是,在 SVG 中,矩形是根据其左上角定位的(xy 属性)。因此,我们需要使用 x- 和 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());

最后,您可以添加一个轴以在顶部显示刻度线。您还可以计算填充样式(甚至渐变)来改变正值和负值的外观差异。把它们放在一起:

关于d3.js - 具有负值的条形图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10127402/

相关文章:

javascript - 如何修复 "' d 3' was used before it was defined"错误

html - D3截图转PDF

javascript - topojson/D3/经度+纬度 map

javascript - 如何使用 d3.js 创建像 StackOverflow 信誉图这样的图表?

javascript - .attr 与 D3.js 中的 .classed

javascript - 将 d3.js 中的一种可视化集成到 Android 应用程序中

r - 将手动编辑的 htmlwidget 导出为 SVG 或类似文件

d3.js - d3-zoom mouseup 事件解决方法

javascript - Nvd3图表不同时区

javascript - 如何用线连接D3中的点?