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

D3.js柱状图数据更新后Y轴刻度标签无法正常更新求助

D3.js柱状图Y轴刻度更新问题解决

问题描述

切换数据集时,Y轴刻度标签无法随新数据更新,仍保留旧数据的标签,且数值与刻度点不匹配。需求是数据更新时Y轴始终显示3个刻度,分别对应「Low」「Medium」「High」。

问题根源

原代码使用d3.scaleOrdinal将数据中的唯一值映射到标签,但D3的.ticks(3)生成的是基于Y轴定义域的均匀分布刻度,并非数据中的唯一值,导致刻度值与序数刻度的定义域不匹配,标签显示异常。

解决方案

移除序数刻度,直接通过手动指定刻度值+索引匹配标签的方式实现需求:

  • 手动指定Y轴的三个刻度值:0、最大值/2、最大值,确保固定显示3个刻度
  • 在tickFormat中根据刻度的索引直接返回对应标签

修正后的关键代码段

const maxing = d3.max(data.map(d=>d.value))
const sy = d3.scaleLinear()
  .domain([0, maxing])
  .range([height, 0]);

// 手动指定三个固定刻度值
const tickValues = [0, maxing / 2, maxing];

const xAxis = d3.axisBottom(sx);
const yAxis = d3.axisLeft(sy)
  .tickValues(tickValues) // 强制使用指定刻度
  .tickFormat((d, i) => {
    // 根据索引返回对应标签
    const labels = ["Low", "Medium", "High"];
    return labels[i];
  });

完整修正代码

JavaScript代码

const outerWidth = 600;
const outerHeight = 300;
const margin = 60;
const height = outerHeight - 2*margin;
const width = outerWidth - 2*margin;

var data = [
{ group: 'A', value: 5 },
{ group: 'B', value: 15 },
{ group: 'C', value: 10 },
{ group: 'D', value: 15 },
{ group: 'E', value: 10 },
{ group: 'F', value: 5 },
];

const update = (data)=>{
const svg = d3.select("#containerSvg")
  .attr("width", outerWidth)
  .attr("height", outerHeight);

const graph = svg
  .select("#graphGroup")
  .attr("transform", "translate(" + margin + "," + margin +")");

const sx = d3.scaleBand()
  .domain(data.map(d => d.group))
  .range([0, width])
  .padding(.1);

const maxing = d3.max(data.map(d=>d.value))
const sy = d3.scaleLinear()
  .domain([0, maxing])
  .range([height, 0]);

// 手动指定三个刻度值,确保固定显示3个刻度
const tickValues = [0, maxing / 2, maxing];

const xAxis = d3.axisBottom(sx);
const yAxis = d3.axisLeft(sy)
  .tickValues(tickValues)
  .tickFormat((d, i) => {
    const labels = ["Low", "Medium", "High"];
    return labels[i];
  });

const bar = graph.selectAll(".bar").data(data);

bar.join("rect")
  .attr('class', 'bar')
  .attr("x", d => sx(d.group))
  .attr("y", d => sy(d.value))
  .attr("width", sx.bandwidth())
  .attr("height", d => height - sy(d.value));

svg.select("#XAxis")
  .attr("transform", "translate(" + margin + "," + height + ")")
  .call(xAxis)

svg.select("#YAxis")
  .attr("transform", "translate(" + margin + ",0)")
  .call(yAxis)
}

update(data);

const buttonData1Access = document.getElementById("Data-button1")
const buttonData2Access = document.getElementById("Data-button2")
const buttonData3Access = document.getElementById("Data-button3")
const buttonData4Access = document.getElementById("Data-button4")

buttonData1Access.addEventListener("click" , (e)=>{
data = [
{ group: 'A', value: 5 },
{ group: 'B', value: 15 },
{ group: 'C', value: 10 },
{ group: 'D', value: 15 },
{ group: 'E', value: 10 },
{ group: 'F', value: 5 },
]
update(data);
})
buttonData2Access.addEventListener("click" , (e)=>{
data = [
{ group: 'y', value: 9 },
{ group: 'o', value: 3 },
{ group: 'u', value: 1 },
{ group: 'D', value: 8 },
{ group: 'E', value: 17 },
{ group: 'F', value: 5 },
]
update(data);
})
buttonData3Access.addEventListener("click" , (e)=>{
data = [
{ group: 'D', value: 1 },
{ group: 'E', value: 3 },
{ group: 'F', value: 9 },
{ group: 'y', value: 9 },
{ group: 'o', value: 3 },
{ group: 'u', value: 1 },
]
update(data);
})
buttonData4Access.addEventListener("click" , (e)=>{
data = [
{ group: 'y', value: 9 },
{ group: 'o', value: 3 },
{ group: 'u', value: 1 },
{ group: 'D', value: 8 },
{ group: 'E', value: 17 },
{ group: 'F', value: 5 },
]
update(data);
})

HTML代码

<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/7.6.1/d3.min.js"></script>
<div class="centered">
  <button class="button cancel-button" id="Data-button1">Data 1</button>
  <button class="button accept-button" id="Data-button2">Data 2</button>
   <button class="button cancel-button" id="Data-button3">Data 3</button>
  <button class="button accept-button" id="Data-button4">Data 4</button>
</div>
<svg id="containerSvg">
  <g id="graphGroup">
     <g id="XAxis"></g>
     <g id="YAxis"></g>
  </g>
</svg>

额外修正说明

原代码中X/Y轴的transform位置存在偏移错误,已一并修正:

  • X轴增加了水平margin偏移,避免被左侧边距遮挡
  • Y轴增加了水平margin偏移,确保刻度标签显示在正确位置

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:20:36