javascript d3.js - 在时间尺度上均匀分布的条

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12186366/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:31:45  来源:igfitidea点击:

d3.js - evenly spaced bars on a time scale

javascriptchartsaxisd3.js

提问by Matt Parker

I'm building a bar plot in d3.js in which each bar represents total TB cases during a month. The data essentially consists of a date (initially strings in %Y-%m format, but parsed using d3.time.format.parse) and an integer. I'd like the axis labels to be relatively flexible (show just year boundaries, label each month, etc.), but I'd also like the bars to be evenly spaced.

我正在 d3.js 中构建一个条形图,其中每个条形表示一个月内的总结核病例。数据基本上由一个日期(最初是 %Y-%m 格式的字符串,但使用 d3.time.format.parse 解析)和一个整数组成。我希望轴标签相对灵活(仅显示年份边界、每个月的标签等),但我也希望条形间隔均匀。

I can get flexible axis labeling when I use a date scale:

当我使用日期刻度时,我可以获得灵活的轴标签:

var xScaleDate = d3.time.scale()
    .domain(d3.extent(thisstat, function(d) { return d.date; }))
    .range([0, width - margin.left - margin.right]);

... but the bars aren't evenly spaced due to varying numbers of days in each month (e.g., February and March are noticeably closer together than other months). I can get evenly-spaced bars using a linear scale:

...但由于每个月的天数不同(例如,2 月和 3 月明显比其他月份更接近),条形图的间隔不均匀。我可以使用线性刻度获得均匀间隔的条形:

var xScaleLinear = d3.scale.linear()
      .domain([0, thisstat.length])
      .range([0, width - margin.left - margin.right]);

... but I can't figure out how to then have date-based axis labels. I've tried using both scales simultaneously and only generating an axis from the xScaleDate, just to see what would happen, but the scales naturally don't align quite right.

...但我不知道如何使用基于日期的轴标签。我试过同时使用两个比例尺,并且只从 生成一个轴xScaleDate,只是为了看看会发生什么,但是比例尺自然不会对齐。

Is there a straightforward way to achieve this that I'm missing?

有没有一种直接的方法来实现我所缺少的?

回答by coquin

You can combine ordinal and time scales:

您可以组合序数和时间尺度:

// Use this to draw x axis
var xScaleDate = d3.time.scale()
    .domain(d3.extent(thisstat, function(d) { return d.date; }))
    .range([0, width - margin.left - margin.right]);

// Add an ordinal scale
var ordinalXScale = d3.scale.ordinal()
    .domain(d3.map(thisstat, function(d) { return d.date; }))
    .rangeBands([0, width], 0.4, 0);

// Now you can use both of them to space columns evenly:
columnGroup.enter()
    .append("rect")
    .attr("class", "column")
    .attr("width", ordinalXScale.rangeBand())
    .attr("height", function (d) {
        return height - yScale(d.value);
    })
    .attr("x", function (d) {
        return xScaleDate(d.date);
    })
    .attr("y", function (d){
        return yScale(d.value);
    });

I've created an example a while ago to demonstrate this approach: http://codepen.io/coquin/pen/BNpQoO

我刚才创建了一个例子来演示这种方法:http: //codepen.io/coquin/pen/BNpQoO

回答by Andrew

I had the same problem, I've ended up accepting that some months are longer than others and adjusting the column bar width so that the gap between bars remains constant. So tweaking the barPath function in the crossfilter home page demo (http://square.github.com/crossfilter/ - uses d3) I got something like this:

我遇到了同样的问题,我最终接受了某些月份比其他月份长的事实,并调整了列栏宽度,以便栏之间的间隙保持不变。所以在 crossfilter 主页演示(http://square.github.com/crossfilter/ - 使用 d3)中调整 barPath 函数我得到了这样的东西:

var colWidth = Math.floor(x.range()[1] / groups.length) - 1;//9;
if (i < n - 1) {
     //If there will be column on the right, end this column one pixel to the left
      var nextX = x(groups[i+1].key)
      colWidth = nextX - x(d.key) - 1;
}
path.push("M", x(d.key), ",", height, "V", yVal, "h",colWidth,"V", height);

回答by Paulo

Try d3.scale.ordinal:

尝试d3.scale.ordinal

    var y = d3.scale.ordinal()
     .domain(yourDomain)
     .rangeRoundBands([0, chartHeight], 0.2);

Tweek 0.2parameter.

Tweek 0.2参数。