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

如何在D3.js中使用scaleOrdinal绘制X轴为字符串的折线图

D3.js v7 离散字符串X轴折线图实现方案

问题根因

  • 你使用的scaleOrdinal不适用于离散分类均匀排布的坐标轴场景,且d3.extent()只会提取X轴字段的首尾两个值作为定义域,中间的分类未被纳入比例尺映射,最终导致渲染结果不符合预期。
  • 针对离散字符串分类X轴、均匀排布、两端留内边距的需求,D3提供了专门的scaleBand比例尺,可直接满足需求。

核心调整点

  1. 替换X轴比例尺为scaleBand,定义域传入所有X轴字符串值,可通过paddingOuter参数单独调整两端内边距大小,paddingInner调整分类之间的间隙。
  2. 折线生成器的X坐标需要加上xScale.bandwidth()/2,让折线的节点对齐对应分类标签的正中心,避免偏移。

调整后完整代码

const data = [{str: 'a',   num: 1}, {str: 'b', num: 3}, {str: 'c', num: 2}, {str: 'd', num: 0}];
// 基础配置参数可按需修改
const margin = {top: 20, right: 20, bottom: 30, left: 40},
    width = 600 - margin.left - margin.right,
    height = 400 - margin.top - margin.bottom;

const svg = d3.select("body").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})`);

// 替换为scaleBand比例尺
const xScale = d3.scaleBand()
   .domain(data.map(d => d.str))
   .range([0, width])
   // 分类之间无间隙,两端留10%宽度的内边距,可按需调整数值
   .paddingInner(0)
   .paddingOuter(0.1);

const yScale = d3.scaleLinear()
   .domain([0, 5])
   .range([height, 0]);

svg.append("g")
   .attr("transform", `translate(0,${height})`)
   .call(d3.axisBottom(xScale))
   .style('color', '#80ffffff')
   .style('font-size', 20)
   .selectAll("text")
   .style("text-anchor", "end")
   .attr("dx", "-.8em")
   .attr("dy", ".15em");

svg.append("g")
   .call(d3.axisLeft(yScale))
   .style('color', '#80ffffff');

const valueline = d3.line()
   .x(d => xScale(d.str) + xScale.bandwidth() / 2)
   .y(d => yScale(d.num));

svg.append("path")
   .data([data])
   .attr("class", "line")
   .attr("d", valueline)
   .style("fill", "none")
   .style("stroke", '#ff0000ff')
   .style("stroke-width", 1);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.07 09:54:03