如何在D3.js中使用scaleOrdinal绘制X轴为字符串的折线图
D3.js v7 离散字符串X轴折线图实现方案
问题根因
- 你使用的
scaleOrdinal不适用于离散分类均匀排布的坐标轴场景,且d3.extent()只会提取X轴字段的首尾两个值作为定义域,中间的分类未被纳入比例尺映射,最终导致渲染结果不符合预期。 - 针对离散字符串分类X轴、均匀排布、两端留内边距的需求,D3提供了专门的
scaleBand比例尺,可直接满足需求。
核心调整点
- 替换X轴比例尺为
scaleBand,定义域传入所有X轴字符串值,可通过paddingOuter参数单独调整两端内边距大小,paddingInner调整分类之间的间隙。 - 折线生成器的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
相关产品推荐
相关产品推荐

