MooTools 1.4 源碼分析 - Fx.CSS

 本文參考了我佛山人的Mootools1.2的源碼分析二十九 -- Fx.CSS

 

  1. /* 
  2. --- 
  3.  
  4. name: Fx.CSS 
  5.  
  6. description: Contains the CSS animation logic. Used by Fx.Tween, Fx.Morph, Fx.Elements. 
  7.  
  8. license: MIT-style license. 
  9.  
  10. requires: [Fx, Element.Style] 
  11.  
  12. provides: Fx.CSS 
  13.  
  14. 源碼分析: 苦苦的苦瓜(http://hmking.blog.51cto.com) 
  15.  
  16. ... 
  17. */ 
  18.  
  19. /** 
  20. * @Fx.CSS: 跟CSS有關的動畫的基類,這裏的動畫,主要是從一個開始值到結束值的變化效果 
  21. **/ 
  22. Fx.CSS = new Class({ 
  23.  
  24.     // 繼承自Fx 
  25.     Extends: Fx, 
  26.  
  27.     // prepares the base from/to object 
  28.     /** 
  29.     * @method: prepare 
  30.     * @param element - (object) 特效作用的元素對象 
  31.     * @param property - (string) CSS屬性 
  32.     * @param values - (mixed) 包含開始值和結束值的數組或一個單值(結束值) 
  33.     * @returns: (object) - 包含from和to兩個鍵值的對象字面量 
  34.     * @description: 動畫的開始和結束值的前期處理 
  35.     * @notes: 此時from和to兩個鍵的值爲數組類型 
  36.     **/ 
  37.     prepare: function (element, property, values) { 
  38.         // 把變量values數組化,因爲values可能傳一個單值,也可能是一個數組 
  39.         values = Array.from(values); 
  40.         // 取特效的起始值和結束值,如果如果只傳了一個值,則本值將作爲結束值,CSS屬性的當前值爲特效起始值 
  41.         if (values[1] == null) { 
  42.             values[1] = values[0]; 
  43.             values[0] = element.getStyle(property); 
  44.         } 
  45.         // 將數組中的項使用parse方法解釋 
  46.         var parsed = values.map(this.parse); 
  47.         // 返回from和to兩個鍵值的對象字面量 
  48.         return { from: parsed[0], to: parsed[1] }; 
  49.     }, 
  50.  
  51.     //parses a value into an array 
  52.     /** 
  53.     * @method: parse 
  54.     * @param value - (mixed) CSS屬性值 
  55.     * @returns: (array) - 數組項值爲包含value和parser兩個鍵值的對象字面量,存儲解釋過的CSS屬性值和包含針對此屬性值的解釋器 
  56.     * @description: 解析一個CSS屬性值爲一個數組 
  57.     **/ 
  58.     parse: function (value) { 
  59.         // 使用lambad表達式,將value函數化之後再執行,這樣的好處是使傳的值可以是function,也可以是固定值 
  60.         value = Function.from(value)(); 
  61.         // 數組化,如果是字符串類型,使用空格分隔成數組 
  62.         value = (typeof value == 'string') ? value.split(' ') : Array.from(value); 
  63.         // 對數組逐項處理 
  64.         return value.map(function (val) { 
  65.             // 轉爲字符類型 
  66.             val = String(val); 
  67.             var found = false
  68.             Object.each(Fx.CSS.Parsers, function (parser, key) { 
  69.                 // 第一項時這裏爲false繼續執行下面,找到合適的解釋器後found判斷不再爲false,避免重複解釋 
  70.                 if (found) { return; } 
  71.                 // 嘗試使用解釋器解釋值 
  72.                 var parsed = parser.parse(val); 
  73.                 // 如果解釋成功,記錄解釋後的值和使用的解釋器(因爲還要使用解釋器的compute和serve方法) 
  74.                 if (parsed || parsed === 0) { 
  75.                     found = { 
  76.                         value: parsed, 
  77.                         parser: parser 
  78.                     }; 
  79.                 } 
  80.             }); 
  81.             // 默認使用字符串值的解釋器 
  82.             found = found || { 
  83.                 value: val, 
  84.                 parser: Fx.CSS.Parsers.String 
  85.             }; 
  86.             return found; 
  87.         }); 
  88.     }, 
  89.  
  90.     // computes by a from and to prepared objects, using their parsers. 
  91.     /** 
  92.     * @method: compute 
  93.     * @param from - (array) 解釋過的CSS屬性的起始值的數組 
  94.     * @param to - (array) 解釋過的CSS屬性的結束值的數組 
  95.     * @param delta - (mixed) 特效變化所需要的比例因子 
  96.     * @returns: (array) 包含計算過的特效當前CSS屬性值信息的一個數組 
  97.     * @description: 根據初始值,結束值和比例因子求目標值 
  98.     **/ 
  99.     compute: function (from, to, delta) { 
  100.         var computed = []; 
  101.         // 取數項小的遍歷 
  102.         (Math.min(from.length, to.length)).times(function (i) { 
  103.             // 返回計算過的值和使用的解釋器 
  104.             computed.push({ 
  105.                 value: from[i].parser.compute(from[i].value, to[i].value, delta), 
  106.                 parser: from[i].parser 
  107.             }); 
  108.         }); 
  109.         // 爲typeOf提供精準類型值 
  110.         computed.$family = Function.from('fx:css:value'); 
  111.         return computed; 
  112.     }, 
  113.  
  114.     // serves the value as settable 
  115.     /** 
  116.     * @method: serve 
  117.     * @param value - (mixed) CSS屬性目標值,此參數可以是一個解釋過的CSS屬性值數組,也可以爲一個CSS屬性值 
  118.     * @param unit - (string 默認爲 false) 計量單位(如: 'px', 'em', 或 '%'). 
  119.     * @returns: (array) 包含計算過的特效當前CSS屬性值信息的一個數組 
  120.     * @description: 對計算過的CSS屬性值數組對象做最後的包裝處理,使其可應用於Element.setStyle方法 
  121.     **/ 
  122.     serve: function (value, unit) { 
  123.         // 如果值未經解釋,需要先解釋(比如單獨調用set方法) 
  124.         if (typeOf(value) != 'fx:css:value') { 
  125.             value = this.parse(value); 
  126.         } 
  127.         var returned = []; 
  128.         value.each(function (bit) { 
  129.             // 得到最終的使用值 
  130.             returned = returned.concat(bit.parser.serve(bit.value, unit)); 
  131.         }); 
  132.         return returned; 
  133.     }, 
  134.  
  135.     // renders the change to an element 
  136.     // 因爲類本身是跟CSS有類,所以最終將計算出的數組通過setStyle反映到element的相應CSS屬性上 
  137.     render: function (element, property, value, unit) { 
  138.         element.setStyle(property, this.serve(value, unit)); 
  139.     }, 
  140.  
  141.     // searches inside the page css to find the values for a selector 
  142.     // 從當前頁面的樣式中查找指定選擇符的樣式設置 
  143.     search: function (selector) { 
  144.         // 模擬緩存,先從臨時對象中找相應鍵值,提高效率 
  145.         if (Fx.CSS.Cache[selector]) { return Fx.CSS.Cache[selector]; } 
  146.         var to = {}, 
  147.                 selectorTest = new RegExp('^' + selector.escapeRegExp() + '$'); 
  148.         // 遍歷當前頁面的樣式表 
  149.         Array.each(document.styleSheets, function (sheet, j) { 
  150.             var href = sheet.href; 
  151.             // 忽略跨域的外鏈樣式表 
  152.             if (href && href.contains('://') && !href.contains(document.domain)) { 
  153.                 return
  154.             } 
  155.             // 樣式規則集 
  156.             var rules = sheet.rules || sheet.c***ules; 
  157.             // 遍歷每條規則 
  158.             Array.each(rules, function (rule, i) { 
  159.                 if (!rule.style) { return; } 
  160.                 // 選擇符(類型選擇符的話會轉爲小寫) 
  161.                 var selectorText = (rule.selectorText) ? rule.selectorText.replace(/^\w+/, function (m) { 
  162.                     return m.toLowerCase(); 
  163.                 }) : null
  164.                 // 匹配指定的樣式選擇符 
  165.                 if (!selectorText || !selectorTest.test(selectorText)) { return; } 
  166.                 // 樣式值分析 
  167.                 Object.each(Element.Styles, function (value, style) { 
  168.                     // 無值 
  169.                     if (!rule.style[style] || Element.ShortStyles[style]) { return; } 
  170.                     // 轉爲字符串 
  171.                     value = String(rule.style[style]); 
  172.                     // 顏色值處理 
  173.                     to[style] = ((/^rgb/).test(value)) ? value.rgbToHex() : value; 
  174.                 }); 
  175.             }); 
  176.         }); 
  177.         // 緩存 
  178.         return Fx.CSS.Cache[selector] = to; 
  179.     } 
  180.  
  181. }); 
  182.  
  183. Fx.CSS.Cache = {}; 
  184.  
  185. // #region - 解釋器 - 
  186.  
  187. // CSS中幾種值類型的解釋器,每個解釋器必須實現parse/compute/serve三個接口 
  188. Fx.CSS.Parsers = { 
  189.  
  190.     // 對顏色的解釋處理 
  191.     Color: { 
  192.  
  193.         parse: function (value) { 
  194.             // 如果是十六進制的顏色表示,處理成RGB數組 
  195.             if (value.match(/^#[0-9a-f]{3,6}$/i)) { 
  196.                 return value.hexToRgb(true); 
  197.             } 
  198.             // 如果是RGB的顏色顯示,正則匹配出RGB數組,不匹配返回flase,以便引擎調用其它解釋器解釋 
  199.             return ((value = value.match(/(\d+),\s*(\d+),\s*(\d+)/))) ? [value[1], value[2], value[3]] : false
  200.         }, 
  201.  
  202.         compute: function (from, to, delta) { 
  203.             // 對R、G和B分別計算目標值 
  204.             return from.map(function (value, i) { 
  205.                 // 可以看到仍然使用靜態的compute方法 
  206.                 return Math.round(Fx.compute(from[i], to[i], delta)); 
  207.             }); 
  208.         }, 
  209.  
  210.         serve: function (value) { 
  211.             // 將R、G、B都轉成數值型 
  212.             return value.map(Number); 
  213.         } 
  214.  
  215.     }, 
  216.  
  217.     // 數值類型的解釋處理 
  218.     Number: { 
  219.  
  220.         // 轉爲浮點數 
  221.         parse: parseFloat, 
  222.  
  223.         // 跟Fx中的算法一樣 
  224.         compute: Fx.compute, 
  225.  
  226.         serve: function (value, unit) { 
  227.             // 加上單位,比如px,pt之類 
  228.             return (unit) ? value + unit : value; 
  229.         } 
  230.  
  231.     }, 
  232.  
  233.     // 對字符類型的解釋處理 
  234.     String: { 
  235.  
  236.         // 解釋器返回false,相當於parse : function(){return false;} 
  237.         parse: Function.from(false), 
  238.  
  239.         // compute方法執行時返回第2個參數 
  240.         compute: function (zero, one) { 
  241.             return one; 
  242.         }, 
  243.  
  244.         // serve方法執行時返回第1個參數 
  245.         serve: function (zero) { 
  246.             return zero; 
  247.         } 
  248.  
  249.     } 
  250.  
  251. }; 
  252.  
  253. // #endregion 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章