響應式卡片抽獎插件 CardShow


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

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

前言

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

當然,博主寫這篇文章不是為了炫耀這個 Demo,而是交流 jQuery 插件的編寫以及這一項目中遇到的各種問題。現在的插件還有很多 bug 以及不完善的地方包括一些代碼的冗余,后期會進行更細致的拆分組裝等。

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

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

jQuery 插件的編寫

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

;(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

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

洗牌算法

 洗牌算法的原始方法由 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 事件

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

本文持續更新~


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM