響應式卡片抽獎插件 CardShow

GitHub: https://github.com/nzbin/CardShow/css

Demo: https://nzbin.github.io/CardShow/html

前言

這個小項目(卡片秀)是一個卡片抽獎特效插件,用開源項目這樣的詞語讓我多少有些羞愧,畢竟做爲一個涉世未深的小夥子,用項目的標準衡量還有很大差距。不過該案例採用 jQuery 插件方式編寫,提供配置參數而且作了瀏覽器兼容優化,總體而言做爲一個小項目也不爲過。目前正在持續更新。css3

固然,博主寫這篇文章不是爲了炫耀這個 Demo,而是交流 jQuery 插件的編寫以及這一項目中遇到的各類問題。如今的插件還有不少 bug 以及不完善的地方包括一些代碼的冗餘,後期會進行更細緻的拆分組裝等。git

首先說一下這個項目的原由,博主最近接到了公司安排的一個抽獎頁面,由於時間倉促以及其它緣由,最後簡單實現了功能而且添加了一些動畫效果。可是最初看到設計圖以卡片形式展現用戶數據的時候,我就想到了可否作的稍微炫酷一點,隨後便一直在構思。好比卡片的飛出、隨機排列、自動及手動抽取以及翻轉顯示等效果。事實證實,把想法變現實會遇到不少的問題。你們能夠點擊 CardShow 查看自動抽卡的效果。目前的效果基本實現了我當初的構思。卡片的抽取效果主要分爲自動抽手動抽兩種。後期會添加卡片拖動的功能。我但願你們可以下載源碼修改參數來查看效果,並提出寶貴意見,以便博主能夠及時做出修改,你們的支持就是我前進的最大動力。github

如下是我在寫插件時遇到的問題以及解決的問題,大概包括 jQuery 插件編寫、modernizr 使用、css3 動畫、transitionend 事件、洗牌算法、相鄰不重複隨機數、獲取 transform 的值、call() 的深刻理解、setTimeout 的堵塞等等,每一塊拿出來均可以單獨寫一篇文章,這篇文章只是簡單介紹,以後也會就某一部分作深刻探討。算法

jQuery 插件的編寫

話說不少事情看着簡單,作起來很難。若是不理解原生 js 的對象、函數、原型、做用域以及 jQuery 的核心思想及方法,想寫一個插件可能真的很是困難。對於 jQuery 插件的編寫我就很少說了,網上一搜不少,比我寫的好的更多,我只貼一下本身寫的插件的結構。對於代碼的結構我思考了好久也研究了好久,最後借鑑了一些案例,感受如下結構更清晰,更簡潔,更易懂。bootstrap

;(function(window, $) {

  // 插件主體
  $.plugin = function(el,options){
    
  }
  // 默認配置
  $.plugin.defaults = {
    
  }
  // 原型方法
  $.plugin.prototype = {
    
  }
 // 設置 jQuery 插件
  $.fn.plugin = function(options) {

    return instance;

  }

})(window, jQuery);

Modernizr 的使用

modernizr 也算是一個老牌的瀏覽器兼容方案了,相信你們也早已使用或者早有耳聞。以前雖然早就知道這個小東西,應該是接觸 bootstrap 時瞭解的,但一直未有機會使用,直到如今寫插件才發現,用它檢測 css3 的屬性並作兼容方案真的是爽歪歪。網上關於 modernizr 的文章並很少,這是官網文檔:https://modernizr.com/docs ,已經說得很詳細,我以後會翻譯該文。數組

相鄰不重複隨機數

解決這個問題多少讓我有一些成就感,雖然還不是很完美。這個問題簡單說就是:寫一個函數,使其能夠持續輸出隨機數,而相鄰位置的隨機數不相同。對於這個問題我沒有搜索到答案,搜到最多的是產生不重複的隨機數。這徹底是兩個問題,這個問題看起來不難,無非定義對比變量,但問題就在於怎麼對比,怎麼寫函數。以前看到有人說「算法就像窗戶紙」,如今深有體會。解決這個問題多少有些運氣的成分,想了好久,最後隨手一寫,居然成功了。可能這個問題自己真的不難。我建議你們先不要展開代碼,本身寫一個函數,用 setInterval 持續輸出隨機數,可否作到相鄰不重複。也但願你們給我一個更完美的方案,歡迎留言。瀏覽器

    // 產生相鄰不重複的隨機數,n 爲隨機數個數
    // 定義比較變量,可否將其封裝在函數內?
    var b = 0;

    function random(n) {
        var a = Math.floor(Math.random() * n);

        if (a == b) {
            return random(n); 
        } else {
            b = a;
            return b;
        }

    };
View Code

 該問題已經獲得解決,具體請參考相鄰不重複隨機數的生成及優化dom

洗牌算法

 洗牌算法的原始方法由 Ronald FisherFrank Yates 提出,網上能夠搜到不少,如下是常見的 JS 方法:

// 數組隨機變換函數
    function shuffleArr(array) {
        var m = array.length,
            t, i;
        // While there remain elements to shuffle…
        while (m) {
            // Pick a remaining element…
            i = Math.floor(Math.random() * m--);
            // And swap it with the current element.
            t = array[m];
            array[m] = array[i];
            array[i] = t;
        }
        return array;
    }; 

如何獲取 transform 的值

由於動畫以 transition 爲主,因此要持續操做元素的 transform 的值。可是 transform 是一個複合值,取出特定數值有必定困難。個人解決辦法簡單粗暴。我在控制檯打印 transform 的值得時候發現是一個 matrix 的東西。關於 transform 的矩陣知識你們自行搜索。其實就是一個字符串,只要 split() 方法取出特定值便可。可是這裏面有個瀏覽器兼容的問題。衆所周知,transform2d 是 3X3 矩陣,而 transform3d 是 4X4 矩陣,若是使用 transform3d 屬性而沒有給出第三個值,在火狐及谷歌瀏覽器會輸出 3X3 矩陣,而在 IE 及 Edge 輸出 4X4 矩陣。

Transitionend 事件

transitionend 事件是在 transition 動畫結束以後執行的函數。說到 transitionend 事件,我有不少感想。首先你們能夠看一下個人 github 中的兩個關於慕課網仿寫 https://github.com/codrops/ScatteredPolaroidsGallery 的 DEMO,當卡片翻轉過來,而後直接移動卡片,這時卡片是邊移動邊翻轉,效果不理想。當初學這個 DEMO 的時候就研究了好久,沒找到答案,直到如今也沒作修改。直到寫此插件才發現一切優化都要基於 transitionend 事件。

Chrome 中的 onresize 事件

關於該問題的詳情及解決方法請參考 這篇文章 !

本文持續更新~

相關文章
相關標籤/搜索