D3学习篇-直方图

  • Post author:
  • Post category:其他




D3直方图相关知识



1. 看代码分析语句,下面的代码实现一个直方图,并且可以实现鼠标事件,选中改变颜色,显示值的功能。

<html>  
  <head>  
        <meta charset="utf-8">  
        <title>8.1.1 鼠标交互</title>  
  </head> 
  <style>
  
.axis path,
.axis line{
	fill: none;
	stroke: black;
	shape-rendering: crispEdges;
}
 
.axis text {
	font-family: sans-serif;
	font-size: 11px;
}
 
  </style>
<body>
 
<script src="https://d3js.org/d3.v4.js"></script>
 
<script>  
 
var dataset = [50, 43, 120, 87, 99, 167, 142];
 
var width  = 600;	//SVG绘制区域的宽度
var height = 400;	//SVG绘制区域的高度
	
var svg = d3.select("body")			//选择<body>
			.append("svg")			//在<body>中添加<svg>
			.attr("width", width)	//设定<svg>的宽度属性
			.attr("height", height);//设定<svg>的高度属性
			
//x轴宽度
var xAxisWidth = 300;
 
//y轴宽度
var yAxisWidth = 300;
			
//x轴比例尺
var xScale = d3.scaleBand()
				.domain(d3.range(dataset.length))
				.range([0,xAxisWidth]);
 
//y轴比例尺
var yScale = d3.scaleLinear()
				.domain([0,d3.max(dataset)])
				.range([0,yAxisWidth]);			
	
//外边框
var padding = { top: 30 , right: 30, bottom: 30, left: 30 };

var text = svg.selectAll("text")
				.data(dataset)

var tips = svg.append("g")
				.attr("class","tips")
				.style("display","none")
				.style('font-size', '10px')
				.style('font-weight', 'bold')
			tips.append("text")
				.attr("x",8)
				.attr("dy",".75em")
/**xScale.invert(d3.mouse(this)[0])

var bisect = d3.bisector(function(d){
	return d.length;
}).left;

bisect(dataset,)**/
var rect = svg.selectAll("rect")
				.data(dataset)		//绑定数据
				.enter()			//获取enter部分
				.append("rect")	//添加rect元素,使其与绑定数组的长度一致
				.attr("fill","steelblue")		//设置颜色为steelblue
				.attr("x", function(d,i){		//设置矩形的x坐标
					return padding.left + xScale(i);
				})
				.attr("y", function(d){		//设置矩形的y坐标
					return height- padding.bottom - yScale(d);
				})
				.attr("width",xScale.bandwidth())		//设置矩形的宽度
				.attr("height",function(d){	//设置矩形的高度
					return yScale(d);
				})
				.on("mouseover",function(d,i){
					d3.select(this)
					  .attr("fill","red");
					  tips.style("display",null);
				})
				.on("mouseout",function(d,i){
					d3.select(this)
					  .transition()
					  .duration(500)
					  .attr("fill","steelblue");
				})
				.on("mousemove",function(d,i) {
					console.log(yScale(d))
					tips.attr("transform","translate("+(padding.left+xScale(i))+","+ (yScale(d)+60)+")");
					tips.select("text").text(d);
					
				});
				
		//绑定数据
			text	
				.enter()				//获取enter部分
				.append("text")			//添加text元素,使其与绑定数组的长度一致
				.attr("fill","white")
				.attr("font-size","14px")
				.attr("text-anchor","middle")
				.attr("x", function(d,i){
					return padding.left + xScale(i);
				})
				.attr("y", function(d){
					return height- padding.bottom - yScale(d);
				})
				.attr("dx",xScale.bandwidth()/2)
				.attr("dy","1em")
				.text(function(d){
					return d;
				});
 



 
var xAxis = d3.axisBottom(xScale);
				
 
yScale.range([yAxisWidth,0]);
				
var yAxis = d3.axisLeft(yScale);
				
				
svg.append("g")
		.attr("class","axis")
		.attr("transform","translate(" + padding.left + "," + (height - padding.bottom) +  ")")
		.call(xAxis);
			
svg.append("g")
		.attr("class","axis")
		.attr("transform","translate(" + padding.left + "," + (height - padding.bottom - yAxisWidth) +  ")")
		.call(yAxis); 
	
</script> 
 
</body>
 
</html>



2. 实现的效果如下图

可以看出,鼠标滑动后,可以改变直方图的颜色,然后可以显示出对应的文字,本文参考的

D3生成柱形图添加鼠标事件(一)

这篇博文,在上面做的基础的改进。

直方图效果图



3. 分析代码中的知识点



X比例尺 scaleBand

原文解释的链接

scaleBand


我觉得意思是构建一个新的比例尺,没有padding和rounding,然后刻度是位于中间的,比如这样

在这里插入图片描述

domain默认是空,range默认是(0-1)

domain(d3.range(dataset.length)) : 以dataset的大小为范围映射X轴的长度xAxisWidth:400



y比例尺 scaleLinear



构建一个连续的刻度标尺。domain和range没有指定值的话默认为[0,1] . 服从函数y = mx+b

domain([0,d3.max(dataset)]):就是找出数据集中最大的值作为上限,由0-167
range([0,yAxisWidth]);	 映射到Y轴【0,300】



selectAll



返回匹配选择器的所有元素,用于选择多个元素



select



返回匹配的第一个元素,用于选择单个元素



tips :添加一个tips作为文字显示的一个查找对象

var tips = svg.append("g")
				.attr("class","tips")
				.style("display","none")
			tips.append("text")
				.style('font-size', '10px')
				.style('font-weight', 'bold')
				.attr("x",20)
				.attr("dy",".75em")
				.attr("text-anchor", "middle")
这样比较合理
初始化时不显示,设定属性display为none
然后把文字的相关属性设置了



然后就是鼠标事件和画直方图

var rect = svg.selectAll("rect")
				.data(dataset)		//绑定数据
				.enter()			//获取enter部分
				.append("rect")	//添加rect元素,使其与绑定数组的长度一致
				.attr("fill","steelblue")		//设置颜色为steelblue
				.attr("x", function(d,i){		//设置矩形的x坐标
					i: 为每个下标的值。0,12,34,56
					xScale(i)0,57,114,171,228,285,342 按照比例尺给定的进行发放大
					return padding.left + xScale(i); 
				})
				.attr("y", function(d){		//设置矩形的y坐标
					
					return height- padding.bottom - yScale(d);
					//同理Y坐标就是从0点到柱形的顶点的位置。比如第一个大约是(30,280)的位置。第一个矩形高大概是89,然后整个直方图是400 400-90-30 = 280
				})
				.attr("width",xScale.bandwidth())		//设置矩形的宽度
				.attr("height",function(d){	//设置矩形的高度
					return yScale(d); //d就是dataset里面的值,然后映射到Y轴的大小
				})
				.on("mouseover",function(d,i){
				鼠标接触后触发的事件-进行颜色改变及文字的状态的改变
					d3.select(this)
					  .attr("fill","red");
					  tips.style("display",null);
				})
				.on("mouseout",function(d,i){
					d3.select(this)
					  .transition()
					  .duration(500)
					  .attr("fill","steelblue");
				})
				.on("mousemove",function(d,i) {
					console.log(yScale(d))
					在鼠标移动过程中,进行文字状态的改变及位置的改变并且显示文字的内容
					tips.attr("transform","translate("+(padding.left+xScale(i))+","+ (yScale(d)+60)+")");
					tips.select("text").text(d);
					
				});



显示直方图中的文字

text	
		.enter()				//获取enter部分
		.append("text")			//添加text元素,使其与绑定数组的长度一致
		.attr("fill","white")
		.attr("font-size","14px")
		.attr("text-anchor","middle")
		.attr("x", function(d,i){
			return padding.left + xScale(i);
		})
		.attr("y", function(d){
			return height- padding.bottom - yScale(d);
		})
		.attr("dx",xScale.bandwidth()/2)
		.attr("dy","1em") 在直方图下1em显示
		.text(function(d){
			return d; 显示的内容
		});



画X轴与Y轴



上面只是把刻度划分好,并没有画出来



var xAxis = d3.axisBottom(xScale);
				
 
yScale.range([yAxisWidth,0]);
				
var yAxis = d3.axisLeft(yScale);
				
				
svg.append("g")
		.attr("class","axis")
		.attr("transform","translate(" + padding.left + "," + (height - padding.bottom) +  ")")
		.call(xAxis);
			
svg.append("g")
		.attr("class","axis")
		.attr("transform","translate(" + padding.left + "," + (height - padding.bottom - yAxisWidth) +  ")")
		.call(yAxis); 
	

链接:

D3 生成柱形图添加鼠标事件



本文并没有用到d3.histogram() 函数,这个函数会生成一个分箱数组,里面包含几个额外的属性,有兴趣可以研究一下


histogram



最后总结一下画直方图的步骤

  • 1.在body中声明SVG的宽高;X轴和Y轴的宽高;外边框

    外边框和X轴,Y轴之和不得超过 SVG绘制域的大小
var width  = 600;	//SVG绘制区域的宽度
var height = 400;	//SVG绘制区域的高度
	
var svg = d3.select("body")			//选择<body>
			.append("svg")			//在<body>中添加<svg>
			.attr("width", width)	//设定<svg>的宽度属性
			.attr("height", height);//设定<svg>的高度属性
			
//x轴宽度
var xAxisWidth = 400;
 
//y轴宽度
var yAxisWidth = 300;

var padding = { top: 30 , right: 30, bottom: 30, left: 30 };
  • 声明X轴比例尺和Y轴比例尺
//x轴比例尺
var xScale = d3.scaleBand()
				.domain(d3.range(dataset.length))
				.range([0,xAxisWidth]);
 
//y轴比例尺
var yScale = d3.scaleLinear()
				.domain([0,d3.max(dataset)])
				.range([0,yAxisWidth]);		
  • 画柱子 + 绑定鼠标事件. 鼠标事件:鼠标到达柱子上后进行颜色的改变,并且显示数值。鼠标划走后变为原来的颜色
//画柱状图
var rect = svg.selectAll("rect")
				.data(dataset)		//绑定数据
				.enter()			//获取enter部分
				.append("rect")	//添加rect元素,使其与绑定数组的长度一致
				.attr("fill","steelblue")		//设置颜色为steelblue
				.attr("x", function(d,i){		//设置矩形的x坐标
				//console.log("xScale(i),"+xScale(i))
					return padding.left + xScale(i);
				})
				.attr("y", function(d){		//设置矩形的y坐标
				console.log(height- padding.bottom - yScale(d));
					return height- padding.bottom - yScale(d);
				})
				.attr("width",xScale.bandwidth())		//设置矩形的宽度
				.attr("height",function(d){	//设置矩形的高度
					console.log("d"+d)
					return yScale(d);
				})
				.on("mouseover",function(d,i){
					d3.select(this)
					  .attr("fill","red");
					  tips.style("display",null);
				})
				.on("mouseout",function(d,i){
					d3.select(this)
					  .transition()
					  .duration(500)
					  .attr("fill","steelblue");
				})
				.on("mousemove",function(d,i) {
					console.log(yScale(d))
					tips.attr("transform","translate("+(padding.left+xScale(i))+","+ (yScale(d)+60)+")");
					tips.select("text").text(d);
					
				});
				
		//绑定数据----显示在柱状图的柱子下面的数值
			text	
				.enter()				//获取enter部分
				.append("text")			//添加text元素,使其与绑定数组的长度一致
				.attr("fill","white")
				.attr("font-size","14px")
				.attr("text-anchor","middle")
				.attr("x", function(d,i){
					return padding.left + xScale(i);
				})
				.attr("y", function(d){
					return height- padding.bottom - yScale(d);
				})
				.attr("dx",xScale.bandwidth()/2)
				.attr("dy","1em")
				.text(function(d){
					return d;
				});
 

  • 鼠标事件滑到柱子上给出值
var tips = svg.append("g")
				.attr("class","tips")
				.style("display","none")
			tips.append("text")
				.style('font-size', '10px')
				.style('font-weight', 'bold')
				.attr("x",20)
				.attr("dy",".75em")
				.attr("text-anchor", "middle")
  • 画X,Y轴
var xAxis = d3.axisBottom(xScale);
				
 
yScale.range([yAxisWidth,0]);
				
var yAxis = d3.axisLeft(yScale);
				
				
svg.append("g")
		.attr("class","axis")
		.attr("transform","translate(" + padding.left + "," + (height - padding.bottom) +  ")")
		.call(xAxis);
			
svg.append("g")
		.attr("class","axis")
		.attr("transform","translate(" + padding.left + "," + (height - padding.bottom - yAxisWidth) +  ")")
		.call(yAxis); 
	



版权声明:本文为ly2230976595原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。