"解決一個問題,最重要的收穫並非獲得的答案。而是在尋找答案的過程當中,學到的其它東西和見識的延伸。"javascript
---《反正我從中學到很多東西》css
」我敬你是條漢子!「html
---《論如何回答女友問爲何對她那麼好》java
css3
//---------------初始化輪顯的方法----------------------- $("#modelSlider").slider({ imgs: [ //圖片的地址 "http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_0f8738e9cfbb9485.png", "http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_89e657a08f9f13f6.png", "http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_884e69c2eb02316b.png", "http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_462506e0ed7b0c25.png", "http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_e5859ff3e6487575.png", "http://images.cnblogs.com/cnblogs_com/lianmin/713650/o_f07bd295f4cdbd7a.png" ], urls: [ //點擊圖片跳轉到的地址,也能夠以下放一段js 'javascript:makeDialog("輪顯提示或者地址","第1個圖",function(){},3)', 'javascript:makeDialog("輪顯提示或者地址","第2個圖",function(){},3)', 'javascript:makeDialog("輪顯提示或者地址","第3個圖",function(){},3)', 'javascript:makeDialog("輪顯提示或者地址","第4個圖",function(){},3)', 'javascript:makeDialog("輪顯提示或者地址","第5個圖",function(){},3)', 'javascript:makeDialog("輪顯提示或者地址","第6個圖",function(){},3)' ], scale: 5 / 2, //圖片寬高比 border: false, //是否顯示分界線 showBar: true, //是否能夠人工切換 x: 4, //橫向格子數 y: 3 //縱向格子數 }); //---------------控制輪顯的方法----------------------- $("#modelSlider").slider("begin"); //開始 執行某個方法 $("#modelSlider").slider("stop"); //中止 $("#modelSlider").slider("choseImg",3); //切換到索引爲3的項 執行某個方法,傳參 $("#modelSlider").slider("resize",{border:true,showBar:false}); //對初始化的屬性進行修改 //-----------試試把上面這4行依次放到控制檯執行一下?------
最初是在一個叫《琉璃神社》的地方看到:http://hacg.club/。觀察了不少次,以爲重點在這裏:格子內的效果切換
。
因而就扒開看看嘍...ajax
總效果
=> 格子特效 + 效果產生順序
格子
=> 2個div + 經過背景圖切換
經過背景圖切換 || 效果產生順序
=> 能夠用jQuery的隊列處理Σ( ゚д゚))
具體的邏輯算法
=> 邊寫邊想吧,寫完重構
我以爲應該寫成插件方式,畢竟要多處用。如下是我寫插件通常的格式,歡迎拍磚:正則表達式
// jQuery 插件的通常寫法,自執行匿名方法 // 好處是這樣的:1.避免其它插件也用了$作關鍵字;2.避免插件內部方法污染全局 // 實際工做中我一個js文件也許會寫大幾十個function,,,沒辦法,需求是一點一點加 (function ($) { function Slider(option) { //深拷貝,修改每一個對象的屬性只能經過對象實例,避免初始化時候外部引用對象的影響 this.opt = $.extend(true, {}, option); } $.fn.slider = function (option) { var defaults = { //默認設置 // 獨立寫出來,也許未來就用獲得呢,也說不定... }; //最終配置 var opt = $.extend({}, defaults, option); //jQuery對象是一個僞數組對象,可能有多個元素 return $.each(this, function (index, ele) { // code... var slider = new Slider(opt); $(ele).data("slider", slider); }); }; })(jQuery);
1.確定要拼接html的,"<div id='"+theId+"' >....... 這種寫法簡直弱爆了,之前也常常這麼寫,可是某天就忽然擴展了,,,果真多讀讀別人的文章對本身有好處.算法
//擴展 string.format String.prototype.format = function () { var args = arguments; var reg = /\{(\d+)\}/g; return this.replace(reg, function (g0, g1) { return args[+g1]; }); }; //用法: "hello {0},your age is {1},so {0}'s age is {1}".format("tom",12); //"hello tom,your age is 12,so tom's age is 12"
2.圖片預加載 編程
(function ($) { // 圖片預加載 $.preLoad = function (urlArr) { $.each(urlArr, function (index, url) { var img = document.createElement("img"); img.src = url; }); } })(jQuery); //上來就加載大量圖片會佔用大量帶寬,影響用戶體驗 //可是若是輪顯這裏不提早加載,只在顯示當前圖片的時候去下載當前圖片,對於通常網速的用戶來講,可能不太好看 //根據實際狀況使用吧...噠?
3.jQuery隊列封裝 api
衆所周知,使用jQuery給元素添加一連串的動畫效果,元素並不會將動畫同時執行,而是按照添加的順序,依次在上一個動畫結束以後纔開始下一個動畫。
我瞭解的狀況就是,jQuery使用了一種叫作「隊列」(queue)的方式將動畫效果依次加進去,在上一個隊列中的動畫執行完畢,經過deferred通知下一個動畫執行。
var ele = $("#id"); //某個jQuery對象 //爲jQuery對象的叫「queueName」的隊列上面添加處理事件 ele.queue("queueName", function (next) { //your code... do something next(); //next() 是執行下一個隊列中要處理的事件,若是沒有next隊列就沒法依次處理 }); //延時 ele.delay(1000, "queueName"); //執行隊列 ele.dequeue("queueName");
這裏要說一下的是,jQuery的動畫默認是把處理事件放在了叫「fx」的隊列中。所以,我進行了如下簡單的封裝:
$.fn.will = function (callback, type) { //這裏的this,表示jQuery對象 this.queue(type || "fx", function (next) { // fx 表示默認的隊列 //這裏的this,是原生的對象 callback && typeof callback == "function" && callback.call($(this)); //使用call,方便回調函數使用this next(); }); return this; //返回this,方便進行鏈式調用 } //試試在控制檯這麼用 var ele = $({}); for (var i = 0; i < 10; i++) { ele.will(function () { console.log(+new Date); }).delay(1000); }
使用隊列,能夠直觀清晰,方便地將異步操做表示出來。就像 Thread.Sleep(1000)
那樣明瞭。
關於Deferred我就不贅述了,本文沒有直接使用到,本身也只是知其然而不知其因此然,僅僅會用。
更詳細的緩動介紹請參見:http://www.cnblogs.com/cloudgamer/archive/2009/01/06/Tween.html
jQuery的animate動畫,我之前不知道在哪裏看到的:只能實現能夠用數字表示的動畫。也就是說css3的transform是不行的。可是animate有一種重載!
經常使用的方式
:
$("html,body").animate({ scrollTop: "0px" }, 1000);
另外一種重載
:
$({ num: 32 }).animate({ num: 64 }, { duration:1000, step: function () { console.log("當前的num是:" + this.num); }, complete: function () { console.log("結束了,num是:" + this.num); } });
【根據要改變的樣式定義一個對象,利用animate改變這個對象,監聽step和complete事件來拼接新的樣式賦值給你要執行動畫的元素!】
如下是【發射憤怒的小鳥】
的具體實現
jQuery.extend(jQuery.easing, { easeOutBounce: function (x, t, b, c, d) { if ((t /= d) < (1 / 2.75)) { return c * (7.5625 * t * t) + b; } else if (t < (2 / 2.75)) { return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b; } else if (t < (2.5 / 2.75)) { return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b; } else { return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b; } },easeOutCubic: function (x, t, b, c, d) { return c * ((t = t / d - 1) * t * t + 1) + b; } }) function sendBirld() { var ele = $("#birld").stop(true, false); ele.css({ "left": "0", "top": "0", "transform": "rotateZ(0deg)" }); $({ left: 0, top: 0, tran: 0 }).animate({ left: 800, top: 180, tran: 360 }, { duration: 2500, specialEasing: { left: 'easeOutCubic', top: 'easeOutBounce' }, step: function () { ele.css({ "left": this.left + "px", "top": this.top + "px", "transform": "rotateZ(" + this.tran + "deg)" }); }, complete: function () { ele.css({ "left": "800px", "top": "180px", "transform": "rotateZ(360deg)" }); } }); }
我目前瞭解到3種js異步的方式:setTimeout,setInterval
,回調函數
,事件觸發
setTimeout和setInterval太醜陋了...雖然大部分偏差能夠接受,可是總歸併非賞心悅目。並且有些東西並不清楚會執行多久,因此捨棄。
事件觸發,讓我想到了 C# 中的事件與委託,確實不錯,可是一長串任務要定義多少事件?感受沉重。 這一塊瞭解的不深,可能說的不正確。
我偏向於第二種回調。
function work(callback) { //do something... typeof callback == "function" && callback(); }
可是天啊,若是一長串方法須要依次執行,這回調要有多難看?
咱們看看jQuery是怎麼作的(只說用法,實現過程沒研究):
$.Deferred()是jQuery1.5開始加進去的,並重寫了 ajax和animate(基於queue,queue基於Deferred)
使用示例:
function work() { var dfd = $.Deferred(); setTimeout(function () { //do something... dfd.resolve(); },1000); return dfd; } work().done(function () { window.console && console.log("結束了"); });
使用方式:1.建立deferred對象;2.爲該對象暴漏的事件綁定方法;3.對象執行動做,觸發綁定的方法
對應的動做和事件(我目前經常使用的):
//參數是若干個deferred或者promise對象 $.when(dfd1, dfd2, dfd3...).done(function () { //全都完成時候觸發 }).fail(function () { //有一個失敗則斷定所有失敗 }).always(function () { //全都是完成或者失敗狀態時候觸發 });
var dfd = $.Deferred(); dfd.done(function (str) { console.log(str); }); dfd.resolve("lalala"); //會打印出 "lalala"
相似於C#中的委託與事件:委託的發佈者不該該將委託的操控權暴漏給訂閱者,最好用事件對委託進行安全的封裝。 直接返回deferred彷佛也不太好,對deferred仍然能夠操做,因此封裝一下:返回deferred.promise(),該對象只暴漏了事件的訂閱方法,而不能操做。
看看 jQuery.ajax
$.ajax({ //... success: function () { //... }, error: function () { //... }, complete: function () { //... } });
ajax方法返回的仍然是一個promise對象,提供事件訂閱的方法:done,fail,then...爲了與原方法名對應,看下圖,也額外提供了原來的名稱:
$.ajax({ //... }).success(function (data) { //原success 或使用 done }).error(function () { //原error 或使用 fail }).complete(function () { //原complete 或相似用使用 always });
這時候我想了想,我要在函數裏面返回deferred對象麼?有點麻煩...
忽然想到jQuery的動畫添加進去就會依次執行。因而瞭解到動畫是基於隊列的:
本文不少地方介紹的可能都不是很詳細,畢竟我以一個「過來人」的思考方式,對於初次接觸人的想法不匹配,相信那些已經掌握的人來講就是:「對啊,就這樣子啊。」,初接觸:「啥?你到底想說啥?」
彷佛有點倉促,可是我以爲了解以上內容就已經夠了。且不行,就當作目錄看,對於各個知識點再去找專門的文章進行深刻學習。
按照最開始的分析,已經解決了:按順序依次延時處理(queue隊列,js異步),jQuery插件的寫法,格子切換時的緩動處理,其中間雜着一些在學習過程當中的思考和擴展(我以爲在尋求答案中的擴展很重要)。 剩下的大概就是具體實現了...無非就是用絕對定位,在切換的時候使用緩動作特效,用queue來進行異步處理,須要一些想法,簡單的算法,html和css基礎。
下面附上下載地址:slider1.2.js ,slider.min.css
我在製做這個插件的過程當中,鞏固和學習了很多知識,實現一個功能,重要的不只僅是實現,更多的是在實現過程當中的自我擴展和見識的延伸。
忽然想到了一個廣告詞:人生就是一部旅行,重要的不是目的地,而是沿途的風景,以及看風景的心情。
您有沒有對這篇文章感興趣呢?
.