有什么不知道的API可以参考D3中文API
也可以去查看别人写的普通柱状图柱状图详解
之前学习d3的时候就看到柱状图中有那种几组几组在一起,今天看到一个demo就是这种几组一起的。
就去仔细看了那个Demo,并且写下这篇文章。
这是V3版本
思路:平时写的写的柱状图都是一个一个,那么怎么将一个柱状图中一个分成好几个呢。
大概的思路就是这样的,其实他写了四个柱状图来将他拼凑在一起,这四个柱状图对应相同的下标的rect放在一起。
var n = 20, // number of samples
m = 4; // number of series
var data=d3.range(m).map(function(){
return d3.range(n).map(Math.random);
})
首先来生成数据,range(m)生成一个长度为4的数组,然后map遍历并且返回一个数组。
然后看return里面:d3.range(n).map(Math.random):这是返回一个长度n的数组并且数值是0-1之间的随机数。
var y = d3.scale.linear()
.domain([0, 1])
.range([height, 0]);
var x0 = d3.scale.ordinal()
.domain(d3.range(n))
.rangeBands([0,width],.2);
var x1=d3.scale.ordinal()
.domain(d3.range(m))
.rangeBands([0,x0.rangeBand()]);
上面总共设置三个比例尺:一个线性两个序数比例尺
y是用来给y轴的,他的domain范围正好对应上面随机生成的0-1之间随机数。根据这个来获取对应高度
x0 比例尺他的范围d3.range(n),既n长度的数组,这就相当于坐标尺分成了N份。
x0.rangeBand()表示的是x0比例尺的区间宽度。每一个元素在值域上面间隔。既1份的宽度
x1比例尺他的范围是d3.range(m),对应的范围是x0的rangeBand(),现在又将这1份的宽度分为m份。既在一份的宽度上面显示多个rect;
<!DOCTYPE html>
<html>
<head>
<title>Grouped Bar Chart</title>
<script type="text/javascript" src='../../js/d3.js'></script>
<style type="text/css">
.axis text {
font: 10px sans-serif;
}
.axis path,
.axis line {
fill: none;
stroke: #000;
shape-rendering: crispEdges;
}
/*将x轴的坐标的横线隐藏*/
.x.axis path {
display: none;
}
</style>
</head>
<body>
<script type="text/javascript">
var n = 20, // number of samples
m = 4; // number of series
//range返回m大小的数组
//map遍历数组并且返回数组
//生成一个二维数组,即4个长度为20的一维数组
var data=d3.range(m).map(function(){
return d3.range(n).map(Math.random);
})
console.log(data);
//设置svg变量和宽高
var margin = {
top: 20,
right: 30,
bottom: 30,
left: 40
},
width = 960 - margin.left - margin.right,
height = 500 - margin.top - margin.bottom;
//设置y轴的比例尺
var y = d3.scale.linear()
.domain([0, 1])
.range([height, 0]);
//设置X轴的比例尺
var x0 = d3.scale.ordinal()
.domain(d3.range(n))
.rangeBands([0,width],.2);
console.log(x0.rangeBand());//上面每一个区间间隔的长度
//设置一个比例尺来求得四个小rect在一个区间的占的长度
var x1=d3.scale.ordinal()
.domain(d3.range(m))
.rangeBands([0,x0.rangeBand()]);
//设置颜色的比例尺
var z=d3.scale.category10();
//x轴的比例尺
var xAxis=d3.svg.axis()
.scale(x0)
.orient('bottom');
//y轴比例尺
var yAxis=d3.svg.axis()
.scale(y)
.orient('left');
//添加svg并且设置宽高并且添加一个g和偏移
var svg=d3.select('body').append('svg')
.attr('width',width+margin.left+margin.right)
.attr('height',height+margin.top+margin.bottom)
.append('svg:g')
.attr("transform","translate("+margin.left+","+margin.top+")");
//添加一个y轴的分组标签
svg.append("g")
.attr("class", "y axis")
.call(yAxis);
//
//添加一个x周到分组标签
svg.append("g")
.attr("class", "x axis")
.attr("transform", "translate(0," + height + ")")
.call(xAxis);
svg.append('g') //添加一个分组g标签
.selectAll('g') //选择所有g元素
.data(data) //绑定数据 即二维数组中的个数4
.enter() //添加数据的标志
.append('g') //添加g元素,也就是数据绑定元素
.style('fill',function(d,i){ //4个元素添加不同颜色。
return z(i);
})
.attr('transform',function(d,i){ //然后移动g标签
// console.log(i);
return "translate("+x1(i)+",0)" ; //x1比例尺的范围是x0的rangeband即一个的区间范围
})
.selectAll('rect') //选择所有的rect,下面将要在每一个g标签里面开始添加20个rect
.data(function(d){
return d; //这里面的每一个d都是一个长度为20的一维数组。
})
.enter() //根据数据开始添加rect
.append('rect')
.attr('width',x1.rangeBand()) //设置x1的rangBand()宽度。
.attr('height',function(d,i){return y(d);}) //设置rect高度
.attr('x',function(d,i){return x0(i);}) //设置rect的x坐标。
.attr('y',function(d){
return height-y(d); //设置y的所在位置
})
</script>
</body>
</html>