使用d3.js画簇状条形图

效果图:

使用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>