Canvas 实现进度条展示统计数据示例

canvas可以画柱状图,如下就是一个例子,主要用到了lineWidth,beginPath,lineCap等知识点。

效果图

源代码

javascript 复制代码
<!DOCTYPE Html>
<html>
<head>
    <title>Line Chart Demo</title>
    <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"/>
</head>
<body>
    <header>预约挂号人数(<span id="hosUnitDiv"></span>)</header>
    <canvas id="canvas2">您的浏览器不支持canvas,请换高版本的浏览器!</canvas>
    <script type="text/javascript" >
	/*进度条图*/
var progressChart = {
  // 绘制chart
  drawChart: function(canvas2, data, padding, marginRight, ygap, bgLineColor, scaleColor) {
    this.canID2 = document.getElementById("canvas2");
    this.content2 = this.canID2.getContext("2d");
    // this.canID2.width = 400;
    var canRealWidth = this.canID2.width - marginRight; // 图像真实的宽度 (距离右边canvas有一定的距离
    var dataMax = this.getArrayMax(data);  // 数据中最大的值
    var unit = this.getUnitByDataMax(dataMax); // 单位
    var xlimt = this.getXLimtByNewData(dataMax / (unit.number)); // x轴刻度 array
    var xgap = (canRealWidth - padding) / (xlimt.length - 1); // x轴刻度间距
    var newData = this.getNewDataByUnit(data, unit.number);
    var ymove = 5; // 整图y轴,向下移动 解决0的时候,显示不全问题
    this.canID2.height = ygap * (data.length) + ymove * 4;
    // 绘制x轴刻度
    for(var i=0; i<xlimt.length; i++) {
      // console.log(i*xgap + padding);
      this.content2.fillStyle = scaleColor;
      // this.content2.textAlign = "left";
      // if语句解决最后一个刻度,靠图像右端对齐问题
      if(i === xlimt.length -1) {
        this.content2.fillText(xlimt[i],i*xgap + padding - 16, ygap*data.length + ygap);
      } else {
        this.content2.fillText(xlimt[i],i*xgap + padding, ygap*data.length + ygap);
      }
    }
    for(var i=0; i<data.length; i++) {
      // 画横线
      this.content2.lineWidth=8;
      this.content2.strokeStyle=bgLineColor;// 笔触颜色
      this.content2.beginPath();
      this.content2.moveTo(padding, ygap*i + ymove);
      this.content2.lineTo(canRealWidth, ygap*i + ymove);
      this.content2.lineCap = 'round';
      this.content2.stroke();
      this.content2.closePath();
      // y轴刻度
      this.content2.fillStyle = scaleColor;
      this.content2.textAlign = "left";//y轴文字靠右写
      // this.content2.textBaseline = "middle";//文字的中心线的调整
      this.content2.font = '12px PingFang HK';  
      this.content2.fillText(data[i].y, 0, ygap*i + 10);

      // 画真实数据线
      /* 画有渐变色线 */
      this.content2.beginPath();
      var linear_gradient = this.content2.createLinearGradient(0,0, canRealWidth,50);
      linear_gradient.addColorStop(0, '#5c80cd');
      linear_gradient.addColorStop(1, '#ac92d3');
      this.content2.strokeStyle = linear_gradient;
      this.content2.lineJoin = 'round';
      this.content2.lineWidth = 8;
      this.content2.strokeRect(padding, ygap*i + ymove, newData[i].x * (canRealWidth - padding) / xlimt[xlimt.length - 1], 0);
    }
    return unit;
  },
  // 根据x轴最大的数据 判断单位 params: 原始数据中最大的值
  getUnitByDataMax: function(maxData) {
    if(maxData > 1000 && maxData <= 10000) {
      return unit = {text: '百人', number: 100};
    } else if(maxData > 10000) {
      return unit = {text: '千人', number: 1000};
    }
  },
  // 获取x轴刻度 params:原始数据通过单位处理后的数据 的最大值
  getXLimtByNewData: function(handleByUnitNewdataMax) {
    if (handleByUnitNewdataMax > 0 && handleByUnitNewdataMax <= 50) {
      return xlimt = [0, 10, 20, 30, 40, 50];
    } else {
      return xlimt = [0, 20, 40, 60 ,80, 100];
    }
  },
  // 根据单位处理原始数据,获取到新的数据
  getNewDataByUnit: function(data, unit) {
    var canvas2NewData = [];
    // var canvas2NewData = canvas2Data.map(function(item) {
    //   item.x = item.x /unit;
    // }); ??? 为什么map不可以
    for (var i = 0; i < canvas2Data.length; i++) {
      canvas2NewData[i] = {y: canvas2Data[i].y, x:canvas2Data[i].x / unit};
    };
    return canvas2NewData;
  },
  // 获取x轴 最大值 
  getArrayMax: function(array) {
    return array.reduce(function(prev, next) {
      if (prev.x > next.x) { return prev.x;} else {return next.x};
    });
  }
}
	</script>
    <script>
      /*进度条图*/
      var canvas2Data = [
        {x:520, y:'1月'},
        {x:1000, y:'2月'},
        {x:600, y:'3月'},
        {x:2100, y:'4月'},
        {x:3400, y:'5月'},
        {x:3600, y:'6月'},
        {x:4000, y:'7月'},
        {x:6000, y:'8月'},
        {x:7000, y:'9月'},
        {x:9000, y:'10月'}
      ];

      var hosUnit = progressChart.drawChart(canvas2, canvas2Data, 30, 10, 13, '#bcc0c7', '#fff');
      document.getElementById('hosUnitDiv').innerText = hosUnit.text;  
    </script>
</body>
</html>