一:引入(主要介绍比例尺)
1.比例尺主要分为两类:定量比例尺和序数比例尺。
定量比例尺主要包括线性比例尺和序数比例尺。它们的主要区别在于定义域是否连续。
2.为什么要使用比例尺?
当遇到页面较大而数据较小时,图形效果较小并且显示不明显,使用比例尺,能在有限空间内最大程度地展示图形效果。
3.为什么要绘制坐标轴?
绘制坐标轴有利于更直观地比较数据之间的差异。
二:思路及代码展示
要实现的效果图:
思路:绘制带坐标轴的柱状图,大体上分为两部分:坐标轴和柱状图。
(1)不含比例尺的柱状图和标签,代码如下:
<script>
//数据
var dataset=[50,43,120,87,99,167,142];
//svg
var width=500;
var height=500;
svg=d3.select("body").append("svg")
.attr("width",width)
.attr("height",height);
//边界
var padding={left:50,right:50,top:50,bottom:50};
//添加矩形
var rects=svg.selectAll("rect").data(dataset).enter().append("rect")
.attr("x",function(d,i){
return padding.left+i*35;
})
.attr("y",function(d,i){
return heightScale-d;
})
.attr("width",30)
.attr("height",function(d,i){return d;})
.attr("fill","blue");
//添加标签
var texts=svg.selectAll("text").data(dataset).enter()
.append("text")
.attr("x",function(d,i){
return padding.left+i*35;
})
.attr("y",function(d,i){
return heightScale-d;
})
.attr("dx",15)
.attr("dy","1em")
.attr("font-size",15)
.attr("text-anchor","middle")
.attr("fill","white")
.text(function(d){return d;});
</script>
结果:
(2)设置X轴和Y轴的比例尺:由效果图显示可知,X轴的值是离散的,选用序数比例尺;Y轴的值是连续的,选用线性比例尺。代码如下:
var widthScale=300;
var heightScale=300;
var xScale=d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeBands([0,widthScale],0.2);
var yScale=d3.scale.linear()
.domain([0,d3.max(dataset)])
.range([0,heightScale]);
(3)绘制含比例尺的矩形(修改(1)中的部分位置即可),代码如下:
<script>
var rects=svg.selectAll("rect").data(dataset).enter().append("rect")
.attr("x",function(d,i){
return padding.left+xScale(i);
})
.attr("y",function(d,i){
return heightScale-yScale(d);
})
.attr("width",xScale.rangeBand())
.attr("height",function(d,i){return yScale(d);})
.attr("fill","blue");
//添加标签
var texts=svg.selectAll("text").data(dataset).enter()
.append("text")
.attr("x",function(d,i){
return padding.left+xScale(i);
})
.attr("y",function(d,i){
return heightScale-yScale(d);
})
.attr("dx",xScale.rangeBand()/2)
.attr("dy","1em")
.attr("font-size",15)
.attr("text-anchor","middle")
.attr("fill","white")
.text(function(d){return d;});
</script>
效果:
(4)绘制坐标轴,代码如下:
yScale.range([heightScale,0]);
xAxis=d3.svg.axis().scale(xScale).orient("bottom");
yAxis=d3.svg.axis().scale(yScale).orient("left");
//添加坐标轴
svg.append("g")
.attr("transform","translate("+padding.left+","+heightScale+")")
.call(xAxis);
svg.append("g")
.attr("transform","translate("+padding.left+","+0+")")
.call(yAxis);
效果:
上面的坐标轴是不是丑爆了?所以,要对坐标轴进行美化啦。
(5)美化坐标轴,设置并应用样式,代码如下:
<style>
.axis path,
.axis line{
stroke: black;
fill:none;
shape-rendering: crispedges;
}
.axis text{
font-family: sans-serif;
font-size: 11px;
}
</style>
<script>
svg.append("g")
.attr("class","axis")
.attr("transform","translate("+padding.left+","+heightScale+")")
.call(xAxis);
svg.append("g")
.attr("class","axis")
.attr("transform","translate("+padding.left+","+0+")")
.call(yAxis);
</script>
效果:
(6)添加交互,当鼠标移到柱形上时,对应的柱形变为红色,移除变为蓝色。
<script>
rects.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","red");
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill","blue");
});
</script>
至此,效果图绘制完毕。
全部代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<script src="d3.js"></script>
<style>
.axis path,
.axis line{
stroke: black;
fill:none;
shape-rendering: crispedges;
}
.axis text{
font-family: sans-serif;
font-size: 11px;
}
</style>
</head>
<body>
<script>
//数据
var dataset=[50,43,120,87,99,167,142];
//svg
var width=500;
var height=500;
svg=d3.select("body").append("svg")
.attr("width",width)
.attr("height",height);
//边界
var padding={left:50,right:50,top:50,bottom:50};
//比例尺
var widthScale=300;
var heightScale=300;
var xScale=d3.scale.ordinal()
.domain(d3.range(dataset.length))
.rangeBands([0,widthScale],0.2);
var yScale=d3.scale.linear()
.domain([0,d3.max(dataset)])
.range([0,heightScale]);
//添加矩形
var rects=svg.selectAll("rect").data(dataset).enter().append("rect")
.attr("x",function(d,i){
return padding.left+xScale(i);
})
.attr("y",function(d,i){
return heightScale-yScale(d);
})
.attr("width",xScale.rangeBand())
.attr("height",function(d,i){return yScale(d);})
.attr("fill","blue");
//交互
rects.on("mouseover",function(d,i){
d3.select(this)
.attr("fill","red");
})
.on("mouseout",function(d,i){
d3.select(this)
.attr("fill","blue");
});
//添加标签
var texts=svg.selectAll("text").data(dataset).enter()
.append("text")
.attr("x",function(d,i){
return padding.left+xScale(i);
})
.attr("y",function(d,i){
return heightScale-yScale(d);
})
.attr("dx",xScale.rangeBand()/2)
.attr("dy","1em")
.attr("font-size",15)
.attr("text-anchor","middle")
.attr("fill","white")
.text(function(d){return d;});
//坐标轴
yScale.range([heightScale,0]);
xAxis=d3.svg.axis().scale(xScale).orient("bottom");
yAxis=d3.svg.axis().scale(yScale).orient("left");
//添加坐标轴
svg.append("g")
.attr("class","axis")
.attr("transform","translate("+padding.left+","+heightScale+")")
.call(xAxis);
svg.append("g")
.attr("class","axis")
.attr("transform","translate("+padding.left+","+0+")")
.call(yAxis);
</script>
</body>
</html>
三:总结
(1)绘制矩形和标签时,一定不要忘了绑定数据。在第一次绘制时,需要使用enter进行添加。
(2)使用比例尺,要根据具体情况选择合适的比例尺,注意各种比例尺之间的区别。
(3)在绘制矩形的时候,要事先想好矩形的位置坐标,便于在加入比例尺时进行位置修改。