Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
SeleniumHQ
GitHub Repository: SeleniumHQ/Selenium
Path: blob/trunk/third_party/closure/goog/fx/anim/anim.js
4143 views
1
/**
2
* @license
3
* Copyright The Closure Library Authors.
4
* SPDX-License-Identifier: Apache-2.0
5
*/
6
7
/**
8
* @fileoverview Basic animation controls.
9
*/
10
goog.provide('goog.fx.anim');
11
goog.provide('goog.fx.anim.Animated');
12
13
goog.require('goog.async.AnimationDelay');
14
goog.require('goog.async.Delay');
15
goog.require('goog.dispose');
16
goog.require('goog.object');
17
18
19
20
/**
21
* An interface for programatically animated objects. I.e. rendered in
22
* javascript frame by frame.
23
*
24
* @interface
25
*/
26
goog.fx.anim.Animated = function() {};
27
28
29
/**
30
* Function called when a frame is requested for the animation.
31
*
32
* @param {number} now Current time in milliseconds.
33
*/
34
goog.fx.anim.Animated.prototype.onAnimationFrame;
35
36
37
/**
38
* Default wait timeout for animations (in milliseconds). Only used for timed
39
* animation, which uses a timer (setTimeout) to schedule animation.
40
*
41
* @type {number}
42
* @const
43
*/
44
goog.fx.anim.TIMEOUT = goog.async.AnimationDelay.TIMEOUT;
45
46
47
/**
48
* A map of animations which should be cycled on the global timer.
49
*
50
* @type {!Object<number, goog.fx.anim.Animated>}
51
* @private
52
*/
53
goog.fx.anim.activeAnimations_ = {};
54
55
56
/**
57
* An optional animation window.
58
* @type {?Window}
59
* @private
60
*/
61
goog.fx.anim.animationWindow_ = null;
62
63
64
/**
65
* An interval ID for the global timer or event handler uid.
66
* @type {?goog.async.Delay|?goog.async.AnimationDelay}
67
* @private
68
*/
69
goog.fx.anim.animationDelay_ = null;
70
71
72
/**
73
* Registers an animation to be cycled on the global timer.
74
* @param {goog.fx.anim.Animated} animation The animation to register.
75
*/
76
goog.fx.anim.registerAnimation = function(animation) {
77
'use strict';
78
var uid = goog.getUid(animation);
79
if (!(uid in goog.fx.anim.activeAnimations_)) {
80
goog.fx.anim.activeAnimations_[uid] = animation;
81
}
82
83
// If the timer is not already started, start it now.
84
goog.fx.anim.requestAnimationFrame_();
85
};
86
87
88
/**
89
* Removes an animation from the list of animations which are cycled on the
90
* global timer.
91
* @param {goog.fx.anim.Animated} animation The animation to unregister.
92
*/
93
goog.fx.anim.unregisterAnimation = function(animation) {
94
'use strict';
95
var uid = goog.getUid(animation);
96
delete goog.fx.anim.activeAnimations_[uid];
97
98
// If a timer is running and we no longer have any active timers we stop the
99
// timers.
100
if (goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
101
goog.fx.anim.cancelAnimationFrame_();
102
}
103
};
104
105
106
/**
107
* Tears down this module. Useful for testing.
108
*/
109
// TODO(nicksantos): Wow, this api is pretty broken. This should be fixed.
110
goog.fx.anim.tearDown = function() {
111
'use strict';
112
goog.fx.anim.animationWindow_ = null;
113
goog.dispose(goog.fx.anim.animationDelay_);
114
goog.fx.anim.animationDelay_ = null;
115
goog.fx.anim.activeAnimations_ = {};
116
};
117
118
119
/**
120
* Registers an animation window. This allows usage of the timing control API
121
* for animations. Note that this window must be visible, as non-visible
122
* windows can potentially stop animating. This window does not necessarily
123
* need to be the window inside which animation occurs, but must remain visible.
124
* See: https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame.
125
*
126
* @param {Window} animationWindow The window in which to animate elements.
127
*/
128
goog.fx.anim.setAnimationWindow = function(animationWindow) {
129
'use strict';
130
// If a timer is currently running, reset it and restart with new functions
131
// after a timeout. This is to avoid mismatching timer UIDs if we change the
132
// animation window during a running animation.
133
//
134
// In practice this cannot happen before some animation window and timer
135
// control functions has already been set.
136
var hasTimer =
137
goog.fx.anim.animationDelay_ && goog.fx.anim.animationDelay_.isActive();
138
139
goog.dispose(goog.fx.anim.animationDelay_);
140
goog.fx.anim.animationDelay_ = null;
141
goog.fx.anim.animationWindow_ = animationWindow;
142
143
// If the timer was running, start it again.
144
if (hasTimer) {
145
goog.fx.anim.requestAnimationFrame_();
146
}
147
};
148
149
150
/**
151
* Requests an animation frame based on the requestAnimationFrame and
152
* cancelRequestAnimationFrame function pair.
153
* @private
154
*/
155
goog.fx.anim.requestAnimationFrame_ = function() {
156
'use strict';
157
if (!goog.fx.anim.animationDelay_) {
158
// We cannot guarantee that the global window will be one that fires
159
// requestAnimationFrame events (consider off-screen chrome extension
160
// windows). Default to use goog.async.Delay, unless
161
// the client has explicitly set an animation window.
162
if (goog.fx.anim.animationWindow_) {
163
// requestAnimationFrame will call cycleAnimations_ with the current
164
// time in ms, as returned from goog.now().
165
goog.fx.anim.animationDelay_ =
166
new goog.async.AnimationDelay(function(now) {
167
'use strict';
168
goog.fx.anim.cycleAnimations_(now);
169
}, goog.fx.anim.animationWindow_);
170
} else {
171
goog.fx.anim.animationDelay_ = new goog.async.Delay(function() {
172
'use strict';
173
goog.fx.anim.cycleAnimations_(goog.now());
174
}, goog.fx.anim.TIMEOUT);
175
}
176
}
177
178
var delay = goog.fx.anim.animationDelay_;
179
if (!delay.isActive()) {
180
delay.start();
181
}
182
};
183
184
185
/**
186
* Cancels an animation frame created by requestAnimationFrame_().
187
* @private
188
*/
189
goog.fx.anim.cancelAnimationFrame_ = function() {
190
'use strict';
191
if (goog.fx.anim.animationDelay_) {
192
goog.fx.anim.animationDelay_.stop();
193
}
194
};
195
196
197
/**
198
* Cycles through all registered animations.
199
* @param {number} now Current time in milliseconds.
200
* @private
201
*/
202
goog.fx.anim.cycleAnimations_ = function(now) {
203
'use strict';
204
goog.object.forEach(goog.fx.anim.activeAnimations_, function(anim) {
205
'use strict';
206
anim.onAnimationFrame(now);
207
});
208
209
if (!goog.object.isEmpty(goog.fx.anim.activeAnimations_)) {
210
goog.fx.anim.requestAnimationFrame_();
211
}
212
};
213
214