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

如何将D3折线图X轴从时间型改为分类型?

将D3时间轴折线图改为字符串分类X轴的修改方案

核心修改点

针对官方折线图示例,需要调整X轴的比例尺、定义域计算和轴生成逻辑,适配字符串类型的分类数据:

  • 替换X轴比例尺类型:原默认使用d3.scaleUtc(时间比例尺),分类字符串数据需改用d3.scaleBand(带比例尺),专门适配离散分类数据。
  • 修正X轴定义域计算:时间轴用d3.extent取极值,但分类轴需要直接使用所有X值的数组来保持数据原有顺序。
  • 调整X轴生成逻辑:分类轴不需要ticks()参数(该参数针对连续轴),直接移除即可确保每个分类标签都显示。
  • 修正折线点位置:带比例尺下,折线点需要定位到每个分类的中间位置,避免偏移。

修改后的LineChart函数代码

LineChart = // Copyright 2021 Observable, Inc.
// Released under the ISC license.
function LineChart(data, {
  x = ([x]) => x, // 提取分类X值
  y = ([, y]) => y, // 提取数值Y值
  defined, // 处理数据间隙
  curve = d3.curveLinear, // 插值方式
  marginTop = 20, // 顶部边距(像素)
  marginRight = 30, // 右侧边距(像素)
  marginBottom = 30, // 底部边距(像素)
  marginLeft = 40, // 左侧边距(像素)
  width = 640, // 外部宽度(像素)
  height = 400, // 外部高度(像素)
  xType = d3.scaleBand, // 替换为分类带比例尺
  xDomain, // X轴定义域(分类数组)
  xRange = [marginLeft, width - marginRight], // X轴范围
  yType = d3.scaleLinear, // Y轴比例尺类型
  yDomain, // Y轴定义域
  yRange = [height - marginBottom, marginTop], // Y轴范围
  yFormat, // Y轴格式字符串
  yLabel, // Y轴标签
  color = "currentColor", // 折线颜色
  strokeLinecap = "round", // 折线端点样式
  strokeLinejoin = "round", // 折线拐点样式
  strokeWidth = 1.5, // 折线宽度(像素)
  strokeOpacity = 1, // 折线透明度
} = {}) {
  // 计算数据值
  const X = d3.map(data, x);
  const Y = d3.map(data, y);
  const I = d3.range(X.length);
  if (defined === undefined) defined = (d, i) => !isNaN(Y[i]); // 分类X值无需判断NaN
  const D = d3.map(data, defined);

  // 计算默认定义域
  if (xDomain === undefined) xDomain = X; // 直接用所有分类值作为X轴定义域
  if (yDomain === undefined) yDomain = [0, d3.max(Y)];

  // 构建比例尺与轴
  const xScale = xType(xDomain, xRange).padding(0.1); // 添加padding让分类间有间隔
  const yScale = yType(yDomain, yRange);
  const xAxis = d3.axisBottom(xScale).tickSizeOuter(0); // 移除ticks参数,显示所有分类标签
  const yAxis = d3.axisLeft(yScale).ticks(height / 40, yFormat);

  // 构建折线生成器
  const line = d3.line()
      .defined(i => D[i])
      .curve(curve)
      .x(i => xScale(X[i]) + xScale.bandwidth() / 2) // 将折线点定位到分类中间
      .y(i => yScale(Y[i]));

  const svg = d3.create("svg")
      .attr("width", width)
      .attr("height", height)
      .attr("viewBox", [0, 0, width, height])
      .attr("style", "max-width: 100%; height: auto; height: intrinsic;");

  svg.append("g")
      .attr("transform", `translate(0,${height - marginBottom})`)
      .call(xAxis);

  svg.append("g")
      .attr("transform", `translate(${marginLeft},0)`)
      .call(yAxis)
      .call(g => g.select(".domain").remove())
      .call(g => g.selectAll(".tick line").clone()
          .attr("x2", width - marginLeft - marginRight)
          .attr("stroke-opacity", 0.1))
      .call(g => g.append("text")
          .attr("x", -marginLeft)
          .attr("y", 10)
          .attr("fill", "currentColor")
          .attr("text-anchor", "start")
          .text(yLabel));

  svg.append("path")
      .attr("fill", "none")
      .attr("stroke", color)
      .attr("stroke-width", strokeWidth)
      .attr("stroke-linecap", strokeLinecap)
      .attr("stroke-linejoin", strokeLinejoin)
      .attr("stroke-opacity", strokeOpacity)
      .attr("d", line(I));

  return svg.node();
}

你的配置代码补充优化

注意给chartWidth赋值(避免宽度异常),修改后代码如下:

<script>
    document.getElementById('chart-title').innerHTML = 'Line Chart';
    const chartColor = '#d13c4b';
    const chartHeight = 500;
    const chartWidth = 800; // 补充宽度赋值
    const yAxisLabel = "↑ Daily close ($)";
    const statusValues = [
        {status: 'PHA', value: phaCat},
        {status: 'Local', value: localCat}
    ];
    
    const chart = LineChart(statusValues, {
        x: d => d.status,
        y: d => d.value,
        width: chartWidth,
        height: chartHeight,
        color: chartColor,
        yLabel: yAxisLabel
    });
    
    document.getElementById("d3_chart").append(chart);
</script>

额外优化建议

如果分类名称较长导致标签重叠,可给X轴标签添加旋转:

// 在调用xAxis的代码块中添加以下内容
.call(g => g.selectAll(".tick text")
    .attr("transform", "rotate(-45)")
    .style("text-anchor", "end")
    .attr("dx", "-.8em")
    .attr("dy", ".15em"))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 23:30:45