利用簡潔的圖片預先載入組件提升h5移動頁面的使用者體驗

來源:互聯網
上載者:User

標籤:

在做h5移動頁面,相信大家一定碰到過頁面已經開啟,但是裡面的圖片還未載入出來的情況,這種問題雖然不影響頁面的功能,但是不利於使用者體驗。拋開網速的原因,解決這個問題有多方面的思路:最基本的,要從http請求合并,緩衝管理,圖片壓縮等方面做效能最佳化;另外就是可以對頁面裡用到的所有圖片做預先載入的處理,當使用者開啟頁面的時候不立即顯示第一屏,而是先顯示資源載入效果,等到載入完畢,再來顯示頁面的主內容,這樣就能解決那個問題。雖然這種載入效果佔用了使用者的瀏覽時間,但是我們可以把它做的好看有趣一點,所以也不會影響使用者體驗。本文實踐了這種想法,提供一個非常簡潔的圖片預先載入組件,實現簡單,功能不弱,在做移動頁面的時候應該對你有參考價值。

效果(代碼下載):

1. 實現思路

html裡面的img標籤和css中background-imag等都會觸發瀏覽器去載入相關的圖片,但是如果這個圖片已經載入過了的話,瀏覽器就會直接使用這張已經載入好的圖片,從而能夠瞬間在頁面中渲染出來。通過javascript,建立Image對象,然後把這些對象的src屬性設定成要載入的圖片地址也能觸發瀏覽器載入圖片,利用這一點就能實現圖片預先載入的功能:在頁面裡首先把那些用到了相關的圖片的元素給藏掉,然後用js去載入圖片,等到所有圖片載入完畢再把藏掉的元素顯示即可。不過這僅僅是一個基本的實現思路,要完成一個功能較健壯的預先載入組件,還有以下三個問題:

1)進度問題

由於預先載入的同時,還得做一個預先載入的效果,這就需要把載入的進度即時通知到外部內容才行。關於進度有兩個實現方式,第一是已載入的資料大小/總的資料大小,第二是已載入的檔案數/總的檔案數,在瀏覽器裡面,採用第一種方式是不現實的,根本沒有原生的辦法可以做到,所以只能採用第二種。

2)圖片載入失敗的問題

比如說有4張圖片,已經載入了50%,在載入第三張的時候出錯了,該不該將進度反饋成75%呢?答案是:應該。如果不這麼處理的話,進度永遠無法到100%,頁面主內容就沒機會顯示了,雖然圖片載入有失敗的情況,但是跟載入器沒有關係,也許圖片本身就不存在呢?也就是說圖片載入失敗不應該影響載入器的功能。

3)圖片載入逾時的問題

圖片不能載入太久,否則使用者一直停留在載入效果上看不到主內容,使用者的等待時間不可控制地延長,導致使用者體驗下降,這樣就有悖載入器的初衷了。所以應該給每個圖片設定一個載入的逾時時間,如果在所有圖片的逾時時間之後,還沒載入完,就應該主動放棄載入,通知外部內容載入完畢,顯示主內容。

綜合以上這些需求,本文提供的實現是:

(function () {    function isArray(obj) {        return Object.prototype.toString.call(obj) === ‘[object Array]‘;    }    /**     * @param imgList 要載入的圖片地址清單,[‘aa/asd.png‘,‘aa/xxx.png‘]     * @param callback 每成功載入一個圖片之後的回調,並傳入“已載入的圖片總數/要載入的圖片總數”表示進度     * @param timeout 每個圖片載入的逾時時間,預設為5s     */    var loader = function (imgList, callback, timeout) {        timeout = timeout || 5000;        imgList = isArray(imgList) && imgList || [];        callback = typeof(callback) === ‘function‘ && callback;        var total = imgList.length,            loaded = 0,            imgages = [],            _on = function () {                loaded < total && (++loaded, callback && callback(loaded / total));            };        if (!total) {            return callback && callback(1);        }        for (var i = 0; i < total; i++) {            imgages[i] = new Image();            imgages[i].onload = imgages[i].onerror = _on;            imgages[i].src = imgList[i];        }        /**         * 如果timeout * total時間範圍內,仍有圖片未載入出來(判斷條件是loaded < total),通知外部環境所有圖片均已載入         * 目的是避免使用者等待時間過長         */        setTimeout(function () {            loaded < total && (loaded = total, callback && callback(loaded / total));        }, timeout * total);    };    "function" === typeof define && define.cmd ? define(function () {        return loader    }) : window.imgLoader = loader;})();

使用方式(對應代碼中的test.html):

<script src="../js/imgLoader.js"></script><script>    imgLoader([‘../img/page1.jpg‘, ‘../img/page2.jpg‘, ‘../img/page3.jpg‘], function(percentage){        console.log(percentage)    });</script>

運行結果:

2. demo說明

本文開篇給出的效果,對應的頁面是index.html,關於這個效果還有兩個問題需要說明:

1)它用了之前這篇部落格利用輪播原理結合hammer.js實現簡潔的滑屏功能介紹的滑屏思路,並把它的一些邏輯封裝在了swipe.js,對外提供了一個全域變數Swipe,這個模組有一個init的方法,以便外部通過調用Swipe.init()就能初始化滑屏相關的功能,原來沒有提供這個init方法,在js載入完畢就會初始化滑屏功能,有了這個init方法就可以把滑屏的邏輯延遲到載入完畢的時候去初始化。index.html一共引用了5個js:

<script src="js/zepto.js"></script><script src="js/transition.js"></script><script src="js/hammer.js"></script><script src="js/imgLoader.js"></script><script src="js/swipe.js"></script>

其中imgLoader.js就是前面介紹圖片載入器的實現,前三個js都是為最後一個swipe.js服務的,感興趣的可以繼續我的部落格利用輪播原理結合hammer.js實現簡潔的滑屏功能瞭解相關內容。不過滑屏不是本文的重點,不瞭解swipe.js不會影響理解本文的內容~

2)雖然我在demo中用到了3張比較大的圖片,但是由於在本地環境,載入速度還是非常快,所以一開始的時候,很難看到預先載入的效果,最後只能想辦法在每個進度回調之前做一下延遲,這才可以看到前面gif圖片一開始的那個loading效果,實現方式是:

//類比載入慢的效果var callbacks = [];imgLoader([‘img/page1.jpg‘, ‘img/page2.jpg‘, ‘img/page3.jpg‘], function (percentage) {    var i = callbacks.length;    callbacks.push(function(){        setTimeout(function(){            var percentT = percentage * 100;            $(‘#loader__info‘).html(‘Loading ‘ + (parseInt(percentT)) + ‘%‘);            $(‘#loader__progress‘)[0].style.width = percentT + ‘%‘;            if (percentage == 1) {                setTimeout(function(){                    $(‘#loader‘).remove();                    Swipe.init();                }, 600);            }            callbacks[i + 1] && callbacks[i + 1]();        },600);    });    if(percentage == 1) {        callbacks[0]();    }});

在真實環境,最好還是不要刻意去加這種延遲,沒必要為了讓使用者看到一個好看有趣的載入效果,就浪費它不必要的等待時間,所以真實環境還是應該用下面的代碼:

imgLoader([‘img/page1.jpg‘, ‘img/page2.jpg‘, ‘img/page3.jpg‘], function (percentage) {    var percentT = percentage * 100;    $(‘#loader__info‘).html(‘Loading ‘ + (parseInt(percentT)) + ‘%‘);    $(‘#loader__progress‘)[0].style.width = percentT + ‘%‘;    if (percentage == 1) {        $(‘#loader‘).remove();        Swipe.init();    }});
3. 注意事項

預先載入是一種比較常見的實現效果,但是在使用的時候,有些問題需要注意:

1)什麼時候用

頁面大的時候用,一般頁面大小超過3M就該考慮使用;頁面內包含資料量比較大的圖片,在手機端測試能夠明顯看到載入緩慢的時候,可以考慮使用。

2)盡量使用sprite圖片

3)載入效果實現的時候,盡量不用圖片,即使要用也應該用很小的圖片,否則載入效果卡在那就沒有意義了。

4. 總結

本文主要介紹了一個簡單的圖片預先載入器,可應用於h5移動頁面的開發當中,在它的思路之下,如果有必要的話,還可以對它進行一些改造,用它來載入其它類型的資源,比如音頻或者視頻檔案,畢竟這些類型的DOM對象也都有提供類似Image對象的屬性和回調。與預先載入的方式相反的,還有一種圖片懶載入的技術,現在網上已經有比較好用的jquery外掛程式了,不過還是很值的去深入瞭解下它的思路跟實現要點,等我有時間去研究研究再寫部落格來介紹,敬請關注!

本文代下載

利用簡潔的圖片預先載入組件提升h5移動頁面的使用者體驗

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.