x 轴文本标签未与 D3.js 中的条形对齐

x-axis text labels not aligned with bars in D3.js

本文关键字:对齐 js D3 文本标签      更新时间:2023-09-26

我使用的是 D3.js直方图布局,并且 x 轴文本标签没有与其各自栏正下方的正确位置对齐。它们似乎以不同的规模运行,但我无法弄清楚为什么它们有不同的间隔。y 轴文本标签与条形的适当高度匹配,但 x 轴文本标签的位置与条形的宽度不同。为什么会这样?

提前谢谢你!

<html>
	<head>
		<script src="//d3js.org/d3.v3.min.js"></script>
		<script src="//d3js.org/d3-random.v0.2.min.js"></script>
		<style>
			html,body{margin:0;padding:0;}
			body {
				background-color: white;
				font-family: Arial;
				width: 100%;
			}
			.title, .axis-text {
				font-weight: bold;
			}
			.axis {
				shape-rendering: crispEdges;
			}
		</style>
	</head>
	<body>
			<svg id="histogram">
			</svg>
			<script>
				function plotHistogram(id, numArray){
					//Initial variables
					var height = 600;
					var width = 600;
					var margin = 60;
					
					//Format our data into bins
					var bins = d3.layout.histogram()
						.bins(numArray.length/5)(numArray);
					
					//Select our SVG and set its attributes
					var svg = d3.select(id)
						.attr("height", height)
						.attr("width", width);
					
					//Create and format x scale
					var xScale = d3.scale.linear()
						.domain(d3.extent(numArray))
						.range([margin, width-margin]);
					
					//Create and format y scale
					var yScale = d3.scale.linear()
						.domain([0,d3.max(bins, function (bin) {
							return bin.y;
						})])
						.range([height - margin, margin]);
					
					//Create and format x axis
					var xAxis = d3.svg.axis()
						.scale(xScale)
						.orient("bottom");
					svg.append("g")
						.attr("class", "axis")
						.attr("transform", "translate(0,"+(height-margin)+")")
						.call(xAxis);
					svg.append("text")
						.attr("text-anchor","middle")
						.attr("x",width/2)
						.attr("y",height-margin/3)
						.text("Data");
					
					//Create and format y axis
					var yAxis = d3.svg.axis()
						.scale(yScale)
						.orient("left");
					svg.append("g")
						.attr("transform", "translate(" + margin + ",0)")
						.attr("class", "axis")
						.call(yAxis);
					svg.append("text")
						.attr("text-anchor","middle")
						.attr("transform","translate("+(margin/3)+","+(height/2)+")rotate(-90)")
						.text("Frequency");
					
					//For every element of our bins variable, create a new rectangle for it
					var randColors = ["#5c5e58","#af6c6f","#c56b18","#97aedc","#5e8477","#9d291f","#2d3361","#55775a"];
					bins.forEach(function (curBin) {
						//console.log(curBin);
						svg.append("rect")
							.attr("class", "bar")
							.attr("fill", function() { return randColors[(Math.floor(Math.random() * randColors.length))]})
							.attr("height", yScale(0) - yScale(curBin.y))
							.attr("stroke","white")
							.attr("width", xScale(curBin.dx)-xScale(0))
							.attr("x", xScale(curBin.x))
							.attr("y", yScale(curBin.y))
					});	
				}
				var randomNumbers = [3, 3, 4, 19, 14, 14, 8, 3, 5, 9, 
8, 5, 18, 15, 1, 6, 18, 20, 6, 19, 
14, 1, 10, 14, 6, 2, 19, 3, 20, 1, 
2, 11, 9, 6, 14, 15, 11, 5, 19, 5, 
17, 16, 9, 12, 19, 13, 20, 20, 13, 6];
				plotHistogram("#histogram",randomNumbers);
			</script>
	</body>
</html>

您的数据值在 1 到 20 的范围内。您的代码在该范围内创建了 10 个箱。每个箱的 dx = 1.9 = (20 - 1)/10。这导致箱阈值为 1、2.9、4.8、6.7、...、18.1、20。您的代码导致刻度值为 2、4、6、...、18、20。由于条柱阈值的间隔为 1.9,刻度值的间隔为 2.0,因此条形与刻度线不一致。

您可以使用以下代码在每个条形的右边缘创建刻度线。

var xAxis = d3.svg.axis()
    .scale(xScale)
    .orient("bottom")
    .tickValues(bins.map(function (bin) { return bin.x + bin.dx; }))
    .tickFormat(d3.format(".1f"));