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

如何使用D3.js解析Date.now()时间戳生成折线图并设置x轴分钟刻度

修复后可用的代码及说明

错误根因梳理

  1. 时间解析逻辑错误:你用的d3.timeParse("%s")仅支持解析10位秒级时间戳,接口返回的timestamp是13位毫秒级时间戳,解析结果为null,传入比例尺后就会生成NaN值,导致路径报错
  2. 比例尺domain设置错误:x轴scaleTime的domain需要传入Date对象,你错误调用了格式化方法timeFormat处理时间戳,生成了非法的字符串入参
  3. 绘图区域偏移错误:你给整个svg元素设置了向下偏移的transform,导致所有元素坐标计算错位
  4. 重复渲染问题:每次useEffect触发都会新增一个svg元素,没有清理旧内容

修正后的代码

useEffect(() => {
  const svgContainer = d3.select(d3Container.current);
  // 先清空旧内容,避免重复渲染
  svgContainer.selectAll("*").remove();

  const margin = { top: 20, right: 20, bottom: 50, left: 70 },
    width = 960 - margin.left - margin.right,
    height = 500 - margin.top - margin.bottom;

  // 13位毫秒时间戳直接转Date对象即可,不需要用parseTime
  const getDate = (timestamp) => new Date(timestamp);

  // 设置x轴10分钟窗口:结束时间为最新数据的时间,开始时间为结束时间减10分钟
  const latestTime = getDate(Math.max(...data.map(d => d.timestamp)));
  const tenMinutesAgo = new Date(latestTime.getTime() - 10 * 60 * 1000);

  // x轴比例尺domain直接传Date对象
  const x = d3.scaleTime()
    .domain([tenMinutesAgo, latestTime])
    .range([0, width]);

  const y = d3.scaleLinear()
    .domain([0, d3.max(data, (d) => d.loadAverage)])
    .nice()
    .range([height, 0]);

  // 时间格式化仅用于刻度展示,不要用于比例尺计算
  const timeFormat = d3.timeFormat("%M:%S");

  const myLine = d3.line()
    .x((d) => x(getDate(d.timestamp)))
    .y((d) => y(d.loadAverage));

  // 绘制主画布
  const svg = svgContainer.append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
    .append("g")
    .attr("transform", `translate(${margin.left}, ${margin.top})`);

  // 绘制折线
  svg.append("path")
    .datum(data)
    .attr("d", myLine)
    .attr("fill", "none")
    .attr("stroke", "steelblue")
    .attr("stroke-width", 1.5)
    .attr("stroke-linejoin", "round")
    .attr("stroke-linecap", "round");

  // 绘制x轴:强制1分钟间隔刻度
  svg.append("g")
    .attr("transform", `translate(0, ${height})`)
    .call(d3.axisBottom(x)
      .ticks(d3.timeMinute.every(1))
      .tickFormat(timeFormat)
    );

  // 绘制y轴
  svg.append("g")
    .call(d3.axisLeft(y));
}, [data]);

关键配置说明

  • 固定10分钟窗口:通过手动计算latestTime和tenMinutesAgo设置x轴domain即可,如果你需要窗口随时间自动滚动,可以将latestTime替换为new Date()
  • 1分钟刻度间隔:通过ticks(d3.timeMinute.every(1))配置x轴,会自动按整分钟生成刻度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 05:48:00