通常在制作时间刻度时,您会使用d3.time.scale(),而不是线性刻度。
您的情况有点奇怪,因为您使用的是抽象的持续时间时间,而不是特定的时间点。不幸的是,d3 的内置时间功能似乎不太适合这种情况。我可以想到几个解决方法:
选项1:使用带有手动的线性刻度.tickValues()
而不是使用Date 对象来格式化您的刻度。您可以简单地将数据值(以秒为单位)分解为小时、分钟和秒。像这样的:
formatMinutes = function(d) {
var hours = Math.floor(d / 3600),
minutes = Math.floor((d - (hours * 3600)) / 60),
seconds = d - (minutes * 60);
var output = seconds + 's';
if (minutes) {
output = minutes + 'm ' + output;
}
if (hours) {
output = hours + 'h ' + output;
}
return output;
};
基本上,这需要总秒数,每 3600 秒创建一个小时,每剩余 60 秒创建一分钟,最后返回剩余的秒数。然后它输出一个字符串表示,例如:17s 或12m 42s 或4h 8m 22s。
然后,当您制作轴时,您可以使用.tickValues() 方法分配从零到数据最大值的范围,步长为 600,因为 10 分钟有 600 秒。看起来像这样:
var x = d3.scale.linear()
.domain([0, d3.max(values)])
.range([0, width]);
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.tickFormat(formatMinutes)
.tickValues(d3.range(0, d3.max(values), 600));
这是输出的JSFiddle。
选项 2:对.ticks() 使用具有固定持续时间的时间刻度
时间刻度让您可以直接指定每 10 分钟的刻度。您只需将 d3 持续时间和乘数传递给轴的 .ticks() 方法即可。像这样:
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.minute, 10)
为此,您必须先设置时间刻度。对于您的规模域,您可以使用一系列毫秒值,因为 d3 会将这些值转换为 Date 对象。在这种情况下,由于您的数据以秒为单位,我们可以简单地乘以 1000 得到毫秒。在这种情况下,我们会将最大值四舍五入到最接近的毫秒,因为它必须是整数才能生成有效日期:
var x = d3.time.scale()
.domain([0, Math.ceil(d3.max(values) * 1000)])
.range([0, width]);
最后,您可以使用.tickFormat() 将格式直接传递给轴:
var xAxis = d3.svg.axis()
.scale(x)
.orient("bottom")
.ticks(d3.time.minute, 10)
.tickFormat(d3.time.format('%Mm %Ss'));
然而,在这一点上我需要指出一些事情,因为正如我所提到的,内置的时间函数并不适合处理抽象的持续时间。我将更改 .tickFormat 以显示小时数:
.tickFormat(d3.time.format('%Hh %Mm %Ss'));
看看JSFiddle会是什么结果...
根据您在世界的哪个位置,您将获得不同的营业时间值。我在美国东海岸,所以我的营业时间是 19。那是从哪里来的?不应该是零吗?
不幸的是,当我们将刻度的域从 0 变为最大数据值的毫秒数时,它创建了常规的 Date 对象,使用这些值作为毫秒输入。这意味着它们表示自 1970 年 1 月 1 日午夜 UTC 时间以来的毫秒数。在美国东部时区,这意味着它是 1969 年 12 月 31 日的 19:00:00。这就是 19 的来源,或您获得的任何其他值。
如果您知道您的所有数据都将少于 1 小时,那么也许您可以忽略这一点。如果您需要使用小时位置,您可以通过强制 d3 使用 UTC 时间来使用 d3.time.format.utc() 格式化轴来解决此问题:
.tickFormat(d3.time.format.utc('%Hh %Mm %Ss'))
JSFiddle 已更新为使用 UTC。
现在您可以看到小时为 0,正如预期的那样。
当然,如果您的任何数据超过 24 小时,则此方法根本不起作用,您将不得不像 选项 1 中那样手动执行坐标轴.
希望这至少可以帮助您入门,但这是一个棘手的问题,而且库中似乎没有内置的优雅解决方案来处理这个问题。也许它会在 d3 的 git repo 上提出一个很好的功能请求。我很想听听@mbostock 是否对如何处理 d3 中的抽象持续时间有任何建议,而不必绑定到需要引用绝对时间点的 Date 对象。