1. 程式人生 > >html5 canvas 實現進度條展示統計資料

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};
    });
  }
}