哆啦的时光机
这里的问题是您正在交换y和height逻辑,它应该是:.attr("y", d => yScale(d.percent)).attr("height", d => height - margin.bottom - margin.top - yScale(d.percent)) 或者,如果您将工作高度设置为...height = totalHeight - margin.bottom - margin.top...它可以只是:.attr("y", d => yScale(d.percent)).attr("height", d => height - yScale(d.percent)) 最重要的是(这解决了您的第二个问题),您错误地使用了 Bostock 的保证金约定。您应该g根据边距翻译该组,然后将所有小节附加到该已翻译组中,而无需再次翻译它们。此外,将轴的组附加到该g组。话虽如此,这是具有这些更改的代码:const data = [{ year: 2012, percent: 50 }, { year: 2013, percent: 30 }, { year: 2014, percent: 90 }, { year: 2015, percent: 60 }, { year: 2016, percent: 75 }, { year: 2017, percent: 20 }];const height = 300;const width = 370;const margin = { top: 20, right: 10, bottom: 20, left: 25};const xScale = d3.scaleBand() .domain(data.map(d => d.year)) .padding(0.2) .range([0, width - margin.right - margin.left]);const yScale = d3 .scaleLinear() .domain([0, 100]) .range([height - margin.bottom - margin.top, 0]);const svg = d3 .select("body") .append("svg") .attr("width", width) .attr("height", height) .style("margin-left", 10);const g = svg .append("g") .attr("transform", `translate(${margin.left}, ${margin.top})`);g .selectAll("rect") .data(data) .enter() .append("rect") .attr("x", d => xScale(d.year)) .attr("y", d => yScale(d.percent)) .attr("width", xScale.bandwidth()) .attr("height", d => height - margin.bottom - margin.top - yScale(d.percent)) .attr("fill", "steelblue")g.append("g") .call(d3.axisLeft(yScale));g.append("g") .call(d3.axisBottom(xScale)) .attr( "transform", `translate(0, ${height - margin.bottom - margin.top})` );<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script>