D3学习篇-直方图
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,1,2,3,4,5,6
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() 函数,这个函数会生成一个分箱数组,里面包含几个额外的属性,有兴趣可以研究一下
最后总结一下画直方图的步骤
-
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 版权协议,转载请附上原文出处链接和本声明。