簡單實用的進度條加載組件loader.js

本文提供一個簡單的方法實現一個流程的進度條加載效果,以便在頁面中能夠經過它來更好地反饋耗時任務的完成進度。要實現這個功能,首先要考慮怎樣實現一個靜態的進度條效果,相似下面這樣的:css

image

這個卻是比較簡單,兩個div便可,bootstrap官方就提供有多種主題的進度條組件。若是本身要用,參照下別人的代碼,寫成本身的風格便可,實際上也很是的好理解:html

.progress {
    height: 20px;
    background-color: #f5f5f5;
    border-radius: 4px;
    box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}

.progress-bar {
    float: left;
    width: 0;
    height: 100%;
    font-size: 12px;
    line-height: 20px;
    color: #fff;
    text-align: center;
    background-color: #337ab7;
    box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
    position: relative;
    border-radius: 4px;
}

第二步,就是該考慮下如何來計算進度。以資源加載爲例,若是是客戶端,一般咱們是有權限去讀取資源實際大小的,因此在計算加載進度的時候,只要拿已加載的數據量除以要加載的總的數據量便可;可是在網頁端,咱們沒有這個能力去拿到要加載的資源的大小,因此只能採用一個不那麼準確的方案,用已加載的資源個數除以總的資源個數。基於後面的計算方法,咱們只須要在每一個耗時任務完成的時刻,計算好已完成的任務進度,而後給進度條設置相應的寬度便可。jquery

下面我用定時器模擬了4個同時發起,可是須要不一樣時間才能完成的異步任務來實現這一步的功能:git

<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
    <link href="loader.css" rel="stylesheet">
</head>
<body>
<div id="loader" class="loader">
    <div class="progress">
        <div class="progress-bar progress-bar-striped">
            <div class="progress-value"></div>
        </div>
    </div>
</div>
</body>
<script src="jquery.js"></script>
<script>
    var $bar = $('#loader').find('.progress-bar');
    var $value = $bar.find('.progress-value');

    var Task = function (index, duration) {
        setTimeout(function () {
            var p = (index / 4 * 100).toFixed(0) + '%';
            $bar.css('width',p);
            $value.text(p);
            console.log('' + index + '個異步任務執行完畢');
        }, duration);
    };

    //模擬四個同時發起的異步任務
    var task1 = new Task(1, 1000);
    var task2 = new Task(2, 3000);
    var task3 = new Task(3, 5000);
    var task4 = new Task(4, 7000);
</script>
</html>

實際效果以下:github

1

當到這一步的時候,其實就已經實現了一個基本的進度條加載功能了。可是上面的效果看起來其實體驗不是很好,要是這個進度條的各個進度值可以連續地變化起來就行了,就像下面這樣:bootstrap

2

爲了作到這一步,有的人可能會想到去利用transition,經過給進度條設置一個width .2s相似的transition,那麼當進度條寬度變化的天然就能看到進度條連續變化的效果了。這種方式有兩個問題:異步

1. 數字沒法連續變化,由於數字從一個值變成另外一個值沒法經過transition進行過渡;動畫

2. 看不到進度條加載到100%,由於當耗時任務完成進度爲100%的時候,除了設置進度條的寬度爲100%,通常還會有的邏輯都是隱藏或移除掉進度條,而進度條由於有transition的做用,從它原來的寬度過渡到100%還須要必定的時間,因此用戶看不到100%了。spa

不過這兩個都不是大問題,沒有進度數字的進度條也很常見;進度條不到100%就進入主功能場景的效果也很常見,並且這種效果有時還能給用戶一種錯覺,就是好像真的加載地很快。。code

假如要糾結以上兩個問題,作一個有數字跟進度都知足連續變化,而且必定要在進度條百分百顯示完加載效果以後才進入主場景的功能,該如何實現?就像下面的這個相似效果:

3

在這個要求中,我以爲有兩個點須要注意:

一是當一個任務完成的時候,剩下的任務可能都尚未完成,這個時候進度條就會進入等待狀態,要等到其它任務完成,有了新的進度以後才能看到下一次的加載效果;

二是進度條加載到100%時的回調控制,當任務完成進度爲100%的時候,進度條可能還不到100%,等進度條從它當前值變到100%的時候,還須要時間,因此原來在任務完成進度爲100%的時候添加的一些進入主場景之類的邏輯,就要換到進度條加載到100%的那個時刻去處理了。

綜合以上,個人思路是:

1. 把進度條的變化分紅多段,由於每次耗時任務的完成,都會對應一個進度值,這些值大於0且小於等於100,以四個耗時任務爲例,它們會把進度條分紅:0-25, 25-50, 75-100三段;

2. 把第1步的分段抽象成一個進度條的加載任務,這個任務有兩個基本屬性:加載時間,變化區間。把這個任務作成一個動畫,在動畫的每次執行過程當中,給外部提供一個回調,並傳入當前的進度值,以便設置進度條的寬度。當前的進度值能夠根據動畫已經執行的時間,加載時間和變化區間來計算。變化區間對應的就是第1步裏面的百分比範圍。加載時間能夠經過變化區間範圍 * 進度條加載1%須要的時間計算獲得。也就是說要把動畫加載1%須要的時間做爲一個常量。爲了更方便一點,把動畫從0加載100%須要的時間做爲一個常量更好控制一些。

3. 定義一個隊列,用來存放第2步抽象的加載任務。控制好隊列第一個任務的執行時機;每執行一個任務,就自動執行下一個。

4. 當任務進度是100%而且隊列裏的最後一個任務完成的時候,通知外部進行回調。

基於這個思路,個人最終實現是(裏面有較詳細的註釋):

https://github.com/liuyunzhuge/blog/blob/master/progress_bar/loader.js

使用的方式能夠參考(結合demo看上面的源碼,會更容易理解):

http://liuyunzhuge.github.io/blog/progress_bar/demo3.html

這個demo的實際效果就跟前面的那個gif如出一轍。

到此爲止,咱們就獲得了一個看起來還比較實用的進度條加載效果控制的組件。不過它也不是沒有問題,它的問題在於:進度條加載完成的時間必定會大於咱們在前面第2步設置的那個進度條一次性從0加載到100%須要的時間。也就是說這個作法會故意延遲整個耗時任務的過程。因此在實際使用的時候,前面說的那個常量不能定義太長了。

最後補充下,這個組件結合我以前寫的一個關於作圖片預加載的組件一塊兒使用,能夠作出更完美的圖片預加載效果,感興趣的能夠嘗試一下。

但願本文的內容對你們的實際工做有所幫助,謝謝閱讀:)

相關文章
相關標籤/搜索