使用d3.js画簇状条形图
效果图:
直接上代码:
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>簇状条形图</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
html,body{
background-color: #f2f3f5;
}
.month_svg{
height: 400px;
}
.month_svg .axis path, .month_svg .axis line {
stroke: black;
fill: none;
}
</style>
</head>
<body>
<div class="month_svg">
</div>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.min.js"></script>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script type="text/javascript">
// var dataset = {
// x: ["签到","未签到","签退","未签退","迟到","早退","其他"],
// y: [9, 30, 90, 70, 50, 20, 40]
// };
var dataset = [
{
employee_name: "张三",
employee_data: [11,20,30],
},
{
employee_name: "李四",
employee_data: [6,40,50],
},
{
employee_name: "王五",
employee_data: [10,70,30],
},
{
employee_name: "马六",
employee_data: [9,20,80],
},
];
lineHeightSvg(dataset);
function lineHeightSvg(dataset){ //直方图
var padding = { top: 50, right: 40, bottom: 30, left: 60 };
var spanData = ["签到","值班","无班次"]; //标注数组
var rectHeight = 100; //距离 = 3个矩形宽度加上间距
var width = $(".month_svg").width();
var height = dataset.length*rectHeight + padding.top + padding.bottom;
//console.log(height);
var svg = d3.select(".month_svg").append("svg")
.attr("width",width)
.attr("height",height);
// 创建一个分组用来组合要画的图表元素
var main = svg.append('g') // 给这个分组加上main类
.attr('class','main') // 设置该分组的transform属性
.attr('transform', "translate(" + padding.left + ',' + padding.top + ')');
var getColor = d3.scale.category10(); //定义颜色比例尺
svg.selectAll('.spanRect')
.data(spanData)
.enter()
.append('rect')
.attr('class', 'spanRect')
.attr('x', function(d,i){
return i*(width/3) + padding.left;
})
.attr('y', 10)
.attr('width',40)
.attr('height', 30)
.attr('fill', function(d, i) {
return getColor(i);
});
svg.selectAll('.spanText')
.data(spanData)
.enter()
.append('text')
.attr('class', 'spanText')
.attr("x",function(d,i){
return i*(width/3) + padding.left + 45;
})
.attr("y",10)
.attr("text-anchor","left")
.attr("dx",0)
.attr("dy",20)
.text(function(d,i){
return d;
});
var dataNum = []; //得到数字数组
var dataName = []; //得到姓名数组
$.each(dataset,function(i,val){
dataNum = dataNum.concat(val.employee_data);
dataName = dataName.concat(val.employee_name);
});
// 定义x轴的比例尺(线性比例尺)
var xScale = d3.scale.linear()
.domain([0, d3.max(dataNum)]) //domain()定义域
.range([ 0,width - padding.left - padding.right]); //range()值域
// 定义y轴的比例尺(序数比例尺)
var yScale = d3.scale.ordinal()
.domain(dataName)
.rangeRoundBands([0, height - padding.top - padding.bottom]);
// 定义x轴和y轴
var xAxis = d3.svg.axis()
.scale(xScale)
.orient('bottom');
var yAxis = d3.svg.axis()
.scale(yScale)
.orient('left');
// 矩形之间的间距
var rectMargin = 10;
//创建签到矩形条
main.selectAll('.qiandao')
.data(dataset)
.enter()
.append('rect')
.attr('class', 'qiandao')
.attr('x', '0')
.attr('y', function(d,i){
return rectHeight*i + 5;
})
.attr('width','0')
.attr('height', (rectHeight-rectMargin)/3)
.attr('fill', function(d, i) {
return getColor(0);
})
.transition()
.duration(500) //持续时间毫秒
.delay(function(d,i){ //延迟多少毫秒执行
return 200*i;
})
.attr('width', function(d,i){
return xScale(d.employee_data[0]);
});
//创建值班矩形条
main.selectAll('.zhiban')
.data(dataset)
.enter()
.append('rect')
.attr('class', 'zhiban')
.attr('x', '0')
.attr('y', function(d,i){
return rectHeight*i + 5 + (rectHeight-rectMargin)/3;
})
.attr('width','0')
.attr('height', (rectHeight-rectMargin)/3)
.attr('fill', function(d, i) {
return getColor(1);
})
.transition()
.duration(500) //持续时间毫秒
.delay(function(d,i){ //延迟多少毫秒执行
return 200*i;
})
.attr('width', function(d,i){
return xScale(d.employee_data[1]);
});
//创建无班次矩形条
main.selectAll('.noBanci')
.data(dataset)
.enter()
.append('rect')
.attr('class', 'noBanci')
.attr('x', '0')
.attr('y', function(d,i){
return rectHeight*i + 5 + 2*(rectHeight-rectMargin)/3;
})
.attr('width','0')
.attr('height', (rectHeight-rectMargin)/3)
.attr('fill', function(d, i) {
return getColor(2);
})
.transition()
.duration(500) //持续时间毫秒
.delay(function(d,i){ //延迟多少毫秒执行
return 200*i;
})
.attr('width', function(d,i){
return xScale(d.employee_data[2]);
});
// 添加坐标轴元素
main.append('g')
.attr('class', 'axis')
.attr('transform', 'translate(0,' + (height - padding.bottom - padding.top) + ')')
.call(xAxis);
main.append('g')
.attr('class', 'axis')
.call(yAxis);
var danwei = d3.select(".month_svg svg")
.append("text")
.attr("x",width-padding.right)
.attr("y",height-padding.bottom)
.attr("text-anchor","left")
.text("(次)");
main.selectAll('.qiandaoNum') //给签到添加数字
.data(dataset)
.enter()
.append('text')
.attr('class','qiandaoNum')
.attr('x', function(d,i){
return xScale(d.employee_data[0]);
})
.attr('y', function(d,i){
return rectHeight*i + 5;
})
.attr("dx",function(d){
})
.attr("dy",rectHeight/6+3)
.text(function(d){
return d.employee_data[0];
});
main.selectAll('.zhibanNum') //给值班添加数字
.data(dataset)
.enter()
.append('text')
.attr('class','zhibanNum')
.attr('x', function(d,i){
return xScale(d.employee_data[1]);
})
.attr('y', function(d,i){
return rectHeight*i + 5;
})
.attr("dx",function(d){
})
.attr("dy",3*rectHeight/6)
.text(function(d){
return d.employee_data[1];
});
main.selectAll('.noBanciNum') //给无班次添加数字
.data(dataset)
.enter()
.append('text')
.attr('class','noBanciNum')
.attr('x', function(d,i){
return xScale(d.employee_data[2]);
})
.attr('y', function(d,i){
return rectHeight*i + 5;
})
.attr("dx",function(d){
})
.attr("dy",5*rectHeight/6-3)
.text(function(d){
return d.employee_data[2];
});
}
</script>
</body>
</html>