D3.js简单柱状图数值显示颠倒问题排查求助
柱状图数值颠倒问题排查与修复
问题描述
现有300个样本数据:260个未订阅有线电视,40个已订阅,对应占比87%和13%。使用D3.js绘制柱状图时,出现数值颠倒问题:已订阅柱子显示87%、未订阅显示13%,无法定位代码缺陷。
原始代码
const rowConverter = (row) => { row = { age: parseInt(row.age), gender: row.gender, income: parseInt(row.income), kids: parseInt(row.kids), ownHome: row.ownHome === "true", subscribed: row.subscribed === "true", segment: row.segment } return { ...row }; }; const dataset = await d3.csv("./data/CableTVSubscribersData.csv", rowConverter); const margin = { top: 40, bottom: 40, left: 60, right: 20 }; const width = 800 - margin.left - margin.right; const height = 600 - margin.top - margin.bottom; let subscribedCounter = 0; let notSubscribedCounter = 0; dataset.forEach(data => { if (data.subscribed) { subscribedCounter++ } else { notSubscribedCounter++; } }); let barChartRows = [ { name: "Subscribed", amount: subscribedCounter }, { name: "Not Subscribed", amount: notSubscribedCounter }, ]; const dataset2 = barChartRows; const barNames = dataset2.map((d) => d.name) const svg = d3.select(".graph1") .append("svg") .attr("width", width + margin.left) .attr("height", height + margin.top + margin.bottom) .append("g") svg.append('rect') .attr("width", width + margin.left) .attr("height", height + margin.top + margin.bottom) .style("fill", "#e6e6e6"); let xScale2 = d3.scaleBand() .domain(barNames) .rangeRound([0, width- margin.left ]); let yScale2 = d3.scaleLinear() .domain([0, 1]) .rangeRound([height - margin.top, 0]); let xAxis2 = d3.axisBottom(xScale2); let yAxis2 = d3.axisLeft(yScale2); let xAxisGroup = svg.append('g') .attr('class', 'groupAxis') .attr('transform', `translate(${margin.left + margin.right}, ${height})`) .call(xAxis2); let yAxisGroup = svg.append('g') .attr('class', 'incomeAxis') .attr('transform', `translate(${margin.left + margin.right},${margin.top})`) .call(yAxis2) .selectAll("text") .text(function (d) { return d3.format(".0%")(d) }); console.log(dataset2); svg.selectAll('.bar') .data(dataset2) .join( enter => enter .append('rect') .attr("class",(d) => d.name) .attr('x',(d) => xScale2(d.name)+(margin.left + margin.right)*2+10}) .attr('y',(d) => height - yScale2(d.amount/300)) .attr('width',150) .attr('height',(d) => yScale2(d.amount/300)}) )
问题根源
- 柱子坐标与高度计算逻辑错误:
- SVG坐标系中y轴数值向下递增,你设置的
yScale2.rangeRound([height - margin.top, 0])意味着:数值0对应底部(更大的y像素值),数值1对应顶部(更小的y像素值)。 - 原始代码中,柱子y坐标用
height - yScale2(d.amount/300)会让占比越高的柱子位置越靠下;高度用yScale2(d.amount/300)会让占比越高的柱子高度越小,直接导致数值显示颠倒。
- SVG坐标系中y轴数值向下递增,你设置的
- x坐标偏移量不合理:原始x坐标的额外偏移会导致柱子与x轴刻度错位。
修复方案
修改柱子绘制部分的坐标与高度计算逻辑,同时优化x坐标和宽度设置:
svg.selectAll('.bar') .data(dataset2) .join( enter => enter .append('rect') .attr("class",(d) => d.name) // 修正x坐标,与x轴刻度对齐 .attr('x',(d) => margin.left + margin.right + xScale2(d.name)) // 修正y坐标:从y轴起始位置(margin.top)开始,根据刻度值定位柱子顶部 .attr('y',(d) => margin.top + yScale2(d.amount/300)) // 使用scaleBand的带宽自动适配宽度,避免固定值导致重叠 .attr('width', xScale2.bandwidth()) // 修正高度:柱子底部在height位置,减去顶部y坐标得到正确高度 .attr('height',(d) => (height - margin.top) - yScale2(d.amount/300)) )
内容的提问来源于stack exchange,提问作者Spiritdon
相关产品推荐
相关产品推荐

