1. 程式人生 > >基於canvas的儀表盤效果

基於canvas的儀表盤效果

set prop height lap .html pre 動畫 pci 圓形

概述

基於Canvas實現的儀表盤及效果。通過配置參數,可以任意修改儀表盤顏色,刻度,動畫過渡時間等,滿足不同場景下的使用。同時使用原生的Canvas,也是學習Canvas的很好的例子。

詳細

代碼下載:http://www.demodashi.com/demo/13031.html

一、演示效果

儀表盤效果如下:

技術分享圖片

二、項目結構截圖

技術分享圖片

gauge.js文件是canvas儀表盤的主邏輯,demo.html中是使用的方法。

註:本例子只有2個文件,如上圖所示。

三、使用方法

在html中,加入一個canvas的元素,設置寬高為510。

<canvas width=510 height=510 id="gauge"></canvas>
<script src="./gauge.js"></script>

//然後配置儀表盤
var my_canvas_obj= document.getElementById("gauge");
    var gauge2 = new Gauge({
      "tick_length": 12,
      "large_tick_length": 22,
      "tick_thickness": 1,
      "tick_group_length": 9,
      "ticks_groups_begin": 0,
      "total_degrees": 250,
      "total_tick": 101,
      "tick_color": "#666",
      "num_font_size": 18,
      "percent": 0,
      "center_font_size": 172,
      tick_on_color: ‘#f1594e‘,
      cur_score_circle_color: ‘#ff5e52‘,
      center_font_color: ‘#ff5e52‘,
      center_text_unit: ‘%‘,
      animation_duration: 1000,
      "canvas": my_canvas_obj2
    })
    
    // 繪制初始儀表盤初始值0%
    gauge.render()
    setTimeout(function(){
      
      //繪制目標值,90%
      gauge.updatePercent(90)
    }, 1000)

儀表盤通過一系列的配置參數來實現各種顏色,動畫時間,刻度多少等的自定義

* 配置參數
 * 顏色配置
    tick_color: "#555962",  // 未達到的刻度顏色
    tick_on_color: "#527d98", // 已達到的刻度顏色
    on_color_gradient: // 已達到的刻度顏色,漸變效果,詳細參考demo中,guage1。值為Array
                          例如:
                           on_color_gradient: [
                            {
                              color: "#50B517",
                              percent: 0 // 最開始,0%
                            },
                            {
                              color: "#000000",
                              percent: 100 // 結束,100%
                            },
                          ]
                          on_color_gradient 設置之後,tick_on_color則不會生效

    center_font_color: ‘#555962‘, //中間數字顏色  設置為#fff-#000時,表示從左往右漸變
    bg_color: // cavans的背景色

 * 尺寸配置:
    tick_length: 80, // 短刻度長度
    large_tick_length: 110, // 長刻度長度
    tick_thickness: 6, //刻度條寬度
    tick_group_length: 9, //每組內的短刻度個數
    ticks_groups_begin: 0, //起始點
    total_degrees: 240, // 刻度的總角度
    animation_duration: 550, //達到目標值的動畫時間
    total_tick: 101, // 刻度總個數
    show_num: true, // 是否展示長刻度下的數字
    show_center_num: true, // 是否顯示中間大的數字
    center_font_size: 200, //中間數字font-size
    center_num_font_family: ,//中間數字font-family
    num_gap: 1, // 每個刻度之間的間隔值,計算顯示數字時需要
    num_begin: 0, // 起始刻度值
    num_font_size: 24, // 刻度值字體大小
    num_font_family: ‘HanHei SC,PingFang SC,Helvetica Neue Thin, Helvetica, STHeitiSC-Light, Arial, sans-serif‘ // 刻度數字font-family
    
  * 不建議隨意修改的參數
    tickmask_offset: 10 // 刻度值距離刻度的間隔, 單位px,
    center_offset: {
      x: 0,
      y: 0
    }, // 中間數字上下位置的偏移
    circle_radius: 5, // 刻度指示圓形的半徑
    circle_offset: 0 // 刻度指示距離刻度的空隙
    gauge_scale: 1, // 縮放比例

四、代碼實現過程

下面介紹canvas儀表盤的實現過程,代碼邏輯位於gauge.js文件中

技術分享圖片

1.初始化

首先properties中放置了所有配置的默認值。

技術分享圖片

然後將傳入的配置值和默認的配置值就行合並。合並完之後進行一下初始化值的設置。

初始化時,設置一下每一個刻度需要旋轉的角度:

總的刻度角度 / (刻度條的個數 - 1) * Math.PI / 180

2.繪制每一幀

    // 計算一下最初始的角度,也就開始的刻度線相對於水平線的角度
    var starting_deg = (180 - this.total_degrees) / 2;
    // 然後將整個畫布旋轉到初始角度。從左下角可是繪制
    context.rotate(starting_deg * PIDEG);
    // 首先繪制刻度盤上指示刻度的小圓點
    this._drawScoreTipCircle(this._halfCanvasWidth - this.circle_radius, this.circle_radius, 0);
    
    // 繪制刻度線,num_ticks 為總刻度線的條數。
    for(var i = 1; i <= num_ticks; i++) {
      //判斷是刻度線是應該亮起來還是暗的
      var is_on = (((i - 1) / num_ticks) * 100 < this._percent);
      //判斷是長刻度線還是短刻度線
      var _isLargeTick = this._isLargeTick(i)
      var tick_length = _isLargeTick ? this.large_tick_length : this.tick_length;
      
      //獲取不同刻度線的顏色
      var color = this._getTickColor(is_on, i);
      //設置填充色
      context.fillStyle = color;
      // 繪制刻度線,即一個長方形。 由於刻度線分長刻度線和短刻度線,而長刻度線和短刻度線因為長度不同,所以長方形的起點位置不同。
      if (_isLargeTick) {
        // 繪制長刻度線,即一個長方形
        context.fillRect(-1*this._halfCanvasWidth + this.circle_radius * 2 + this.circle_offset, -this.tick_thickness/2, tick_length, this.tick_thickness);
        // 對於整數值的刻度線,旁邊有一個示數,這裏繪制示數
        if (this.show_num) {
          this._drawGaugeNum(tick_length, i);
        }
      } else {
        // 繪制短刻度線
        context.fillRect(-1*this._halfCanvasWidth + this.circle_radius * 2 + this.circle_offset + this.delatLength, -this.tick_thickness/2, tick_length, this.tick_thickness);
      }
      //每畫完一條,就旋轉一下畫布。旋轉的角度 = 總的刻度角度 / (刻度條的個數 - 1) * Math.PI / 180
      context.rotate(this._rotation_deg);
    }
    // 全部繪制完之後,把前一個舊的canvas清除掉
    this._context.clearRect(0, 0, this._canvas.width, this._canvas.height);
    // 繪制新的圖像
    this._context.drawImage(this.canvas, 0, 0);
    // 每次繪制完成後要回到畫布的原始的狀態
    context.restore();

3.動畫

通過上面的 render 函數,我們可以繪制出一個靜態的儀表盤了。接下來我們需要讓儀表盤的示數展示動起來。這裏我們利用 requestAnimationFrame 函數,在函數回調中執行 render 函數,繪制出不一樣的刻度亮/暗圖。

      var lastUpdate = +new Date();
      // 動畫開始時已經亮起來的刻度的百分比
      var start = this._percent;
      // 目標百分比
      var end = this._target_percent;
      // 計算一下每毫秒我們需要完成多少百分比,然後後面每次執行時,根據經過了多少時間來計算出應該完成多少,即刻度應該亮起來多少
      var change_per_ms = (end - start)/duration;
      var increasing = change_per_ms > 0 ? 1 : 0;
      // 首先計算一下所有刻度亮起來時應該是什麽顏色的,保存到一個數組中。
      // 後面動畫過程中直接從數組中取值即可,不需要再次計算。
      this.colorArray = this._gradientColorArray();
      // 更新邏輯
      var update = function () {
        // 通過時間來計算應該完成的百分比
        var now = +new Date();
        var elapsed = now - lastUpdate;
        _this._percent += elapsed*change_per_ms;
        
        lastUpdate= now;
        //檢測一下是否已經達到我們最終的百分比,如果達到了就停止動畫;如果沒有就繼續繪制
        if ((increasing && _this._percent < _this._target_percent) 
          || (!increasing && _this._percent > _this._target_percent)) {
          _this.render();
          _this._requestAnimFrame(update);
        }
        else {
          _this._percent = _this._target_percent;
          _this.render();
        }
      };
      _this._requestAnimFrame(update);

這樣我們的儀表盤就有一開始從0到100刻度逐漸變亮的效果。

代碼下載:http://www.demodashi.com/demo/13031.html

註:本文著作權歸作者,由demo大師發表,拒絕轉載,轉載需要作者授權

基於canvas的儀表盤效果