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

D3.js图表X轴首尾刻度仅显示部分内容的技术问询

D3.js X轴首尾刻度显示异常解决方法

问题现象

使用D3.js绘制时间轴时,X轴首尾两个非整分的刻度仅显示秒数部分,而中间间隔5分钟的整分刻度显示正常。

问题代码

JavaScript代码

let margin = ({ top: 50, right: 50, bottom: 50, left: 100 });
let dim = ({ height: 100, width: 500 });
let svg = d3.select('#foo');

svg.attr('height', dim.height);
svg.attr('width', dim.width);

let dateTimeExtent = [new Date('2023-12-07T08:02:38.000Z'), new Date('2023-12-07T08:10:46.000Z')];
let x = d3.scaleUtc()
  .domain([dateTimeExtent[0], dateTimeExtent[1]])
  .range([margin.left, dim.width - margin.right]);
let ticks = [dateTimeExtent[0], ...d3.utcMinute.every(5).range(dateTimeExtent[0], dateTimeExtent[1]), dateTimeExtent[1]];
/* ticks数组内容:
[
"2023-12-07T08:02:38.000Z",
"2023-12-07T08:05:00.000Z",
"2023-12-07T08:10:00.000Z",
"2023-12-07T08:10:46.000Z"
]*/

// x轴绘制
svg.append('g')
  .attr('transform', `translate(0,${dim.height - margin.bottom})`)
  .call(d3.axisBottom(x)
    .tickValues(ticks)
    .tickSizeOuter(0))
  .call(g => g.selectAll('.tick > text')
    .attr('transform', 'rotate(90) translate(23 -12)')) // 旋转刻度文本
  .call(g => g.append('text')
    .attr('x', dim.width - margin.right)
    .attr('y', -4)
    .attr('fill', 'currentColor')
    .attr('font-weight', 'bold')
    .attr('text-anchor', 'end')
    .text(''));

HTML代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>

<div>
  <svg id='foo'>
  </svg>
</div>

问题原因

D3.js的轴组件会自动根据刻度值的时间粒度选择格式化器:中间的刻度是整分时间(如08:05:00),属于分钟级粒度,默认显示时分;而首尾刻度包含秒数(如08:02:38),时间粒度更细,被自动匹配了只显示秒的格式,导致显示异常。

解决方法

通过.tickFormat()方法统一指定时间格式,覆盖D3的自动格式化逻辑。比如使用d3.utcFormat("%H:%M:%S")显示完整的时分秒,或者根据需求调整格式字符串。

修改后的核心代码

在轴的配置中添加tickFormat:

.call(d3.axisBottom(x)
  .tickValues(ticks)
  .tickSizeOuter(0)
  .tickFormat(d3.utcFormat("%H:%M:%S"))) // 新增:统一时间格式

完整修改后的JavaScript代码

let margin = ({ top: 50, right: 50, bottom: 50, left: 100 });
let dim = ({ height: 100, width: 500 });
let svg = d3.select('#foo');

svg.attr('height', dim.height);
svg.attr('width', dim.width);

let dateTimeExtent = [new Date('2023-12-07T08:02:38.000Z'), new Date('2023-12-07T08:10:46.000Z')];
let x = d3.scaleUtc()
  .domain([dateTimeExtent[0], dateTimeExtent[1]])
  .range([margin.left, dim.width - margin.right]);
let ticks = [dateTimeExtent[0], ...d3.utcMinute.every(5).range(dateTimeExtent[0], dateTimeExtent[1]), dateTimeExtent[1]];

// x轴绘制(添加了tickFormat)
svg.append('g')
  .attr('transform', `translate(0,${dim.height - margin.bottom})`)
  .call(d3.axisBottom(x)
    .tickValues(ticks)
    .tickSizeOuter(0)
    .tickFormat(d3.utcFormat("%H:%M:%S"))) // 统一时间格式
  .call(g => g.selectAll('.tick > text')
    .attr('transform', 'rotate(90) translate(23 -12)'))
  .call(g => g.append('text')
    .attr('x', dim.width - margin.right)
    .attr('y', -4)
    .attr('fill', 'currentColor')
    .attr('font-weight', 'bold')
    .attr('text-anchor', 'end')
    .text(''));

效果说明

修改后,所有刻度都会使用指定的%H:%M:%S格式显示完整的时分秒,首尾刻度的时间信息将完整展示,不会再出现仅显示秒数的情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 17:29:54