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

时间:2016-03-17 14:30:13

标签: javascript d3.js svg

我正在使用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>
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:2)

您的数据值介于1到20之间。您的代码在该范围内创建了10个分区。每个bin都有一个dx = 1.9 =(20 - 1)/ 10.这个结果是bin阈值为1,2.9,4.8,6.7,...,18.1,20。你的代码导致2,4的滴答值, 6,...,18,20。由于bin阈值间隔为1.9,而tick值间隔为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"));