分類:
版權聲明:本文為博主原創文章,未經博主允許不得轉載。
閒話
jQuery的動畫機制有800行, 雖然不如樣式的1300行,難度上卻是不減。由於事前不瞭解animate接口的細節使用規則,看代碼期間吃了很多苦頭,尤其是深惡痛絕的defaultPrefilter函數,靠著猜想和數次的逐行攻略,終於全部拿下。本文將一點一點拆解出jq的動畫機制及具體實現,解析各種做法的目的、解耦的方式、必要的結構、增強的輔助功能。
需要提前掌握queue隊列的知識,css樣式機制、data緩存、deferred對象至少要瞭解核心API的功能。有興趣可以參考我之前的幾篇分析。
(本文採用 1.12.0 版本進行講解,用 #number 來標註行號)
動畫機制
jQuery的動畫機制比較複雜,下面將逐一分析其中要點。
全局Interval
教學時常用的動畫函數demo,結構是下面這樣:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
如何計算每步運動的值需要講究,舉個栗子:
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
方式2為標準的使用法則,方式1雖然很多人仍在使用包括教學,但是會出現如下兩個問題:
問題1:js單線程
JavaScript是單線程的語言,setTimeout、setInterval定時的向語言的任務隊列添加執行代碼,但是必須等到隊列中已有的代碼執行完畢,若遇到長任務,則拖延明顯。對於」方式1」,若在tick內遞歸的setTimout,tick執行完才會再次setTimeout,每次的延遲都將疊加無法被追償。setInterval也不能倖免,因為js引擎在使用setInterval()時,僅當隊列裡沒有當前定時器的任何其它代碼實例時,才會被添加,而次數和值的累加都是需要函數執行才會生效,因此延遲也無法被追償。
問題2:計時器精度
瀏覽器並不一定嚴格按照設置的時間(比如20ms)來添加下一幀,IE8及以下瀏覽器的精度為15.625ms,IE9+、Chrome精度為4ms,ff和safari約為10ms。對於「方式1」這種把時間拆為確定次數的計算方式,運動速度就一點不精確了。
jQuery顯然採用了」方式2」,而且優化了interval的調用。demo中的方式出現多個動畫時會造成 interval 滿天飛的情況,影響性能,既然方式2中動畫邏輯與定時器的時間、調用次數無關,那麼可以單獨抽離,整個動畫機制只使用一個統一的setInterval,把tick推入堆棧
jQuery.timers
,每次定時器調用jQuery.fx.tick()
遍歷堆棧裡的函數,通過tick的返回值知道是否運動完畢,完畢的棧出,沒有動畫的時候就jQuery.fx.stop()
暫停。jQuery.fx.start()
開啟定時器前會檢測是開啟狀態,防止重複開啟。每次把tick推入堆棧的時候都會調用jQuery.fx.start()。這樣就做到了需要時自動開啟,不需要時自動關閉。
[源碼]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
同步、異步
jQuery.fn.animate
jQuery動畫機制最重要的一個考慮是:動畫間便捷的同步、異步操作。
jQuery允許我們通過$().animate()的形式調用,對應的外觀方法是
jQuery.fn.animate( prop, speed, easing, callback )
,內部調用動畫的核心函數Animation( elem, properties, options )
。
上面的demo雖然粗糙,但是思路一致。Animation一經調用,內部的tick函數將被jQuery.fx.timer函數推入jQuery.timers堆棧,立刻開始按照jQuery.fx.interval的間隔運動。要想使動畫異步,就不能立即調用Animation。在回調callback中層層嵌套來完成異步,顯然是極不友好的。jQuery.fn.animate中使用了queue隊列,把Animation函數的調用封裝在doAnimation函數中,通過把doAnimation推入指定的隊列,按照隊列順序異步觸發doAnimation,從而異步調用Animation。
queue隊列是一個堆棧,比如elem的」fx」隊列,jQuery.queue(elem, 「fx」)即為緩存jQuery._data(elem, 「fxqueue」)。每個元素的」fx」隊列都是不同的,因此不同元素或不同隊列之間的動畫是同步的,相同元素且相同隊列之間的動畫是異步的。添加到」fx」隊列的函數若是隊列中當前的第一個函數,將被直接觸發,而添加到其他隊列中的函數需要手動調用jQuery.dequeue才會啟動執行。
如何設置添加的隊列呢?jQuery.fn.animate支持對象參數寫法jQuery.fn.animate( prop, optall),通過 optall.queue指定隊列,未指定隊列的按照默認值」fx」處理。speed、easing、callback均不是必須項,內部通過
jQuery.speed
將參數統一為對象optall。optall會被綁定上被封裝過的optall.complete函數,調用後執行dequeue調用隊列中下一個doAnimation(後面會講Animation執行完後如何調用complete自動執行下一個動畫)
雖然加入了queue機制後,默認的動畫順序變為了異步而非同步。但optall.queue指定為false時,不使用queue隊列機制,doAnimation將立即調用Animation執行動畫,保留了原有的同步機制。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
jQuery.fn.stop/finish
現在我們有了同步、異步兩種方式,但在同步的時候,有可能出現重複觸發某元素動畫,而我們並不需要。在jq中按照場景可分為:相同隊列正在運動的動畫、所有隊列正在運動的動畫、相同隊列所有的動畫、所有隊列的動畫、非隊列正在運動的動畫。停止動畫分為兩種狀態:直接到運動結束位置、以當前位置結束。
實現原理
清空動畫隊列,調用$(elems).queue( type, [] ),會替換隊列為[],也可以事先保存隊列,然後逐個執行,這正是jQuery.fn.finish的原理。停止當前動畫,jQuery.timers[ index ].anim.stop( gotoEnd )。gotoEnd為布爾值,指定停止動畫到結束位置還是當前位置,通過timers[ index ].elem === this && timers[ index ].queue === type匹配隊列和元素,從這裡也能看出Animation函數中的單步運動tick函數需要綁定elem、anim、queue屬性(anim是Animation返回的animation對象,stop函數用來結束當前動畫,後面會詳細講)。
然而並不是添加到隊列的都是doAnimation,比如jQuery.fn.delay(),由於沒調用Animation,所以沒有tick函數,自然沒有anim.stop,從jq源碼中可以看出,推薦在隊列的hook上綁定hooks.stop停止函數(因此stop/finish中會調用hooks.stop)。queue隊列中被執行的函數備註了的next函數(dequeue操作,調用下一個)和對應的hook對象($._data(type+』queuehook')緩存,empty.fire用於自毀)和this(元素elem),因此可以通過next調用下一項。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
jQuery.fn.stop( type, clearQueue, gotoEnd )
:type指定隊列(false會變成」fx」,本方法不能停止非隊列,需要使用jQuery.fn.finish(false));clearQueue為true為清除隊列後續動畫,false為不清除;gotoEnd為true表示直接到運動結束位置,false為當前位置結束
註:type無字符串值時,clearQueue, gotoEnd參數提前,type設為undefined。(對於type為null/undefined的處理很特別。對」fx」按照clearQueue值處理,但是對元素所有隊列動畫都停止,按照goToEnd值處理。非隊列動畫不受影響)
jQuery.fn.finish( type )
:type指定隊列(默認」fx」,false表示非隊列),執行過程中標記jQuery._data( this ).finish=true,清空queue隊列,並且遍歷執行隊列中所有doAnimation函數(有finish屬性的才是doAnimation函數)。由於緩存中帶有finish標記,動畫對象一創建就將調用anim.stop( true )所有動畫直接到結束狀態。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
Animation動畫
jQuery動畫的核心邏輯就是Animation( elem, properties, options ),立即開始一個動畫,把每步動畫tick推入全局interval調用堆棧jQuery.timers,返回一個animation對象(也是promise對象,通過上面的stop方法來實現stop、finish的終止動畫操作)。
tick函數是對properties中多屬性執行動畫。jq用面向對象的思想,把每個屬性的作為一個運動對象tween,把他們依次放入animation.tweens中(一個堆棧[]),使邏輯更分明。Animation內通過時間換算出百分比percent,然後傳入tween.run()來完成計算與設置。
Tween
Tween( elem, options, prop, end, easing )
函數的構造和jq一樣,另Tween.prototype.init.prototype = Tween.prototype,從而Tween()返回一個實例並能夠使用原型方法cur、run。cur負責計算當前屬性值,run需傳入百分比,然後設置到對應的位置。duration是tweens中的tween公用,每步運動的百分比一致,在Animation的tick函數中處理。
每個屬性運動的easing是可以不同的,options.easing可以定義公用樣式,但優先級是低於options.specialEasing.prop這樣對屬性直接指定的,每個屬性的easing屬性可能不一樣。options對象也會被傳入,可以通過指定options.step函數,每個屬性的tween調用都會執行一次,this指定為elem,傳入參數now、tween。
cur和run中使用了
Tween.propHooks[prop].set/get
鉤子。鉤子代表例外,Tween.propHooks._default.get/set(tween)
是標準的處理。scrollTop/scrollLeft有set鉤子。對於通常使用動畫的屬性,非特殊需求需要鉤子的確實幾乎沒有。- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
創建tween對象,使用
createTween( value, prop, animation )
方法。內部會遍歷jQuery.tweeners[「*」]中的函數,默認只有一個函數,調用animation.createTween( prop, value ),核心是調用Tween()。
value支持累加值」+=300」、」+=300px」,普通使用帶不帶單位均可,因為addjustCSS會對tween.start/end進行處理,同一單位,並且轉換為數值,單位存在tween.unit上
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
Animation
上面介紹到Animation返回一個promise對象,有什麼意義呢?在jQuery.speed中封裝的options.complete函數(可以調用dequeue),需要動畫結束時觸發,如果把它綁定在promise對象上,tick函數運動完畢調用resolve,即可觸發complete執行下一個doAnimation。
Animation中,在執行動畫前需要進行修正(即先刪除,再添加修正屬性和值)。
1、propFilter( props, animation.opts.specialEasing ):屬性修正。屬性變為小駝峰,把還會把margin、padding、borderWidth拆分成4個方向
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
2、prefilters隊列:默認只有defaultPrefilter( elem, props, opts ),有四個用途
- 1、當有非隊列動畫執行時,會啟動計數,只要有非隊列動畫沒結束,」fx」動畫隊列的queuehook自毀函數無法順利執行,會等全部結束才執行(用意暫時不明)
- 2、若涉及到height/width的動畫,overflow先設置為hidden,動畫結束改回。通過給animation綁定alway函數實現(stop(false)會觸發reject,也需要改回,所以不綁定done函數)
- 3、對於inline元素涉及到height/width的動畫,需要設置為」inline-block」,jq中的設置時display為none的也要變為顯示運動(這點挺奇怪,因為默認block的塊級如果是none就不會變為顯示)。但對於都是toggle/show/hide設置,但是全部都被過濾的,因為沒有動畫,需要還原為none
- 4、支持屬性值為 「toggle」、」show」、」hide」。會被修正為適當的值。
toggle/show/hide動畫機制
使用時自覺遵守,一個動畫的屬性對象裡只能出現3者中的1種!!
當帶有toggle/show/hide的動畫單獨執行或異步執行時:
- 1、先判斷isHidden,即是否隱藏(display:none)
- 2、隱藏時調用hide無作用(過濾掉),顯示時調用show無作用(過濾掉)
- 3、hide表示把元素prop屬性的值從now運動到0,運動完後調用jQuery( elem ).hide()變為不可見(原理是內部display設為none),但是要把屬性值還原為now。
- 4、show表示把元素prop屬性的值從0運動到now,運動前把不可見狀態通過jQuery( elem ).show()變為可見
- 5、toggle需要判斷當前是否隱藏,當前隱藏調用show,當前顯示調用hide
難點在於帶有toggle/show/hide的動畫同步執行時(同步指的是相同屬性有正在發生的動畫,不同屬性之間按上面規則進行):
- 1、對於同步中排在第一個調用的,完全按照上面的規則
- 2、從上面規則看出,無論show、hide、toggle,運動過程中都是顯示狀態(isHidden=false)
- 3、既然運動中都是顯示狀態,異步時的第2條對同步的動畫(非第一個調用的)不約束。
- 4、第一個動畫執行前會把屬性當前值now緩存到jQuery._data( elem, 「fxshow」),查看是否有該屬性緩存值來判斷誰是同步的動畫(即非第一個)
- 5、對於非第一個的同步動畫,不以自身當前位置為參照,把緩存裡存的now(即第一個運動前的位置)當做hide的運動起點或show的運動終點
- 6、toggle與show和hide不同,運動到相反而不是特定的狀態。當遇到toggle,需要緩存一個要運動到的終點狀態,運動結束立即刪除(例如:show->hide則緩存hide,沒執行完時同步調用toggle會查看緩存值,從而知道當前運動終點是hide->show)
- 7、show、hide判斷是否同步必須相同elem的相同屬性。toggle判斷同步則是針對元素的狀態。toggle判斷無緩存,表示異步調用中,但是也可能是當前正在show、hide。由於show、hide的運動過程中都會為顯示狀態(可能同時有很多,既有show也有hide,duration也不同),因此未查找到toggle記錄的緩存時,統一是運動到隱藏show->hide。
jQuery小bug:
if ( value === 「show」 && dataShow && dataShow[ prop ] !== undefined ) { hidden = true; }之所以需要修改hidden,因為同步的show按照show->hide處理,後面的處理邏輯需要判斷hidden。但是遍歷屬性時,對於第一個動畫的屬性,若為show,變為hidden之前遍歷的不被處理,之後的都將從show->hide,與之前不一致。可以增加一個變量來輔助過濾那些屬性。
if ( value === 「show」 && dataShow && dataShow[ prop ] !== undefined ) { hidden = true; }之所以需要修改hidden,因為同步的show按照show->hide處理,後面的處理邏輯需要判斷hidden。但是遍歷屬性時,對於第一個動畫的屬性,若為show,變為hidden之前遍歷的不被處理,之後的都將從show->hide,與之前不一致。可以增加一個變量來輔助過濾那些屬性。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
最後是核心部分代碼,
Animation( elem, properties, options )
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
toggle/show/hide
jq中提供了幾種便捷的show/hide/toggle動畫封裝。(原理見上小節」toggle/show/hide動畫機制」)
genFx( type, includeWidth )
:type可為show/hide/toggle,將轉換為屬性對象。includeWidth指定是否包含寬度方面動畫變化。
genFx( name, true ) -> { height: name, width: name, opacity: name, marginTop/Right/Bottom/Left: name, paddingTop/Right/Bottom/Left: name }
genFx( name ) -> { height: name, marginTop/bottom: name, paddingTop/bottom: name }
genFx( name ) -> { height: name, marginTop/bottom: name, paddingTop/bottom: name }
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 頂
- 踩
沒有留言:
張貼留言