You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于D3.js在24小时时间轴上计算条形的起始位置与宽度

解决D3.js 24小时时间轴条形图的位置与宽度计算问题

看起来你在实现时间段条形图时,核心问题出在X轴的定义域设置和条形宽度的计算逻辑上,咱们一步步来修正:

1. 修正X轴的时间范围

你当前的X轴定义域是[new Date(), new Date()],这相当于只取了当前时刻,完全覆盖不了24小时的范围。应该把X轴的定义域设为从今天0点到明天0点,也就是完整的24小时区间:

var today = new Date();
today.setHours(0, 0, 0, 0);
var tomorrow = new Date(today);
tomorrow.setDate(today.getDate() + 1); // 明天0点

var xScale = d3.scaleTime()
    .domain([today, tomorrow]) // 完整的24小时区间
    .nice(d3.timeHour, 1) // 按小时刻度优化
    .range([0, width]); // 这里不需要再减margin.left,因为svg已经做了translate

2. 正确计算条形的起始位置与宽度

  • 起始位置:直接用xScale(d.fromHours)就可以,因为d.fromHours已经是转换后的Date对象,X轴比例尺会自动映射到正确的像素位置。
  • 宽度:不能直接对时间差用xScale,应该用结束时间的X坐标减去开始时间的X坐标,也就是xScale(d.toHours) - xScale(d.fromHours)。之前的代码里用了xScale(Math.abs(d.toHours - d.fromHours / 36e5)),这是完全错误的,因为d.toHours - d.fromHours得到的是毫秒数,而xScale只接受Date对象。

修正后的矩形属性设置代码:

var rect = layer.selectAll("rect")
    .data(function(d, i) {
        d.map(function(b) {
            b.colorIndex = i;
            return b;
        });
        return d;
    })
    .enter()
    .append("rect")
    .transition()
    .duration(500)
    .delay(function(d, i) { return i * 10; })
    .attr("y", function(d, i, j) {
        var k = Array.prototype.indexOf.call(j[i].parentNode.parentNode.childNodes, j[i].parentNode);
        return yScale(d.gate) + yScale.bandwidth() / n * k;
    })
    .attr("height", yScale.bandwidth() / n)
    .attr("x", function(d) {
        return xScale(d.fromHours); // 直接用转换后的起始时间
    })
    .attr("width", function(d) {
        return xScale(d.toHours) - xScale(d.fromHours); // 结束位置减开始位置得到宽度
    })
    .attr("class", "bar")
    .style("fill", function(d) {
        return dataset["colors"][d.colorIndex];
    });

3. 其他小调整

  • 你的X轴tickSize(-height)会绘制贯穿整个图表的网格线,这个没问题,但要确保X轴的transform是正确的,应该是translate(0, height),因为svg的g已经做了margin的translate。
  • 修正y轴的选择器,原来的svg.select("g")会选中第一个g元素(也就是我们的主绘图g),应该用svg.append("g")来创建y轴的容器:
svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

测试验证

修改后,你可以在控制台打印xScale(d.fromHours)和xScale(d.toHours)的值,确认它们对应24小时轴上的正确位置,宽度也会是两个位置的差值,这样条形就能准确展示时间段了。

内容的提问来源于stack exchange,提问作者Rajkishan Swami

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 10:15:49