html5 canvas 实现进度条展示统计数据

最终实现效果图:
这里写图片描述

html代码:


<!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" src="chart.js"></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月'}
      ];
      /*
        @param1: 所画图的id
        @param2: 数据
        @param3: 整个所画图像距离canvas左边间距
        @param4: 图像距离右边有一定的间距
        @param5: y轴每条横线及刻度之间间距
        @param6: 背景线,颜色
        @param7: kedu text color
        x轴之间的间距,是通过整个宽度算出来的
        retuan: 根据最大数据,返回单位(目前只算到:百人、千人)
      */
      var hosUnit = progressChart.drawChart(canvas2, canvas2Data, 30, 10, 13, '#bcc0c7', '#fff');
      document.getElementById('hosUnitDiv').innerText = hosUnit.text;  
    </script>
</body>
</html>

script 代码:

/*进度条图*/
/*
  @param1: 所画图的id
  @param2: 数据
  @param3: 整个所画图像距离canvas左边间距
  @param4: 图像距离右边有一定的间距
  @param5: y轴每条横线及刻度之间间距
  x轴之间的间距,是通过整个宽度算出来的
  retuan: 根据最大数据,返回单位
*/
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 = 500;
    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);
      /* 画纯颜色的线 */
      // this.content2.lineWidth="8";
      // this.content2.strokeStyle="#f00";// 刻度颜色
      // this.content2.beginPath();
      // this.content2.moveTo(padding, ygap*i + ymove);
      //  canRealWidth - padding  x轴真正总体的宽度(此处不是图像真实的宽度,要减去其实位置padding的值才是
      //   此处真实数据x轴坐标的计算: x轴真正的宽度 比 x刻度最大的值   等于   真实数据x轴坐标 比 真实除以单位数据的值
      //                           最后还要加上padding, 因为起始位置是padding而不是0 
      // this.content2.lineTo(newData[i].x * (canRealWidth - padding) / xlimt[xlimt.length - 1] + padding, ygap*i + ymove);
      // this.content2.lineCap = 'round';
      // this.content2.stroke();
    }
    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};
    });
  }
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值