OLD | NEW |
(Empty) | |
| 1 // Copyright 2014 Google Inc. All rights reserved. |
| 2 // |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); |
| 4 // you may not use this file except in compliance with the License. |
| 5 // You may obtain a copy of the License at |
| 6 // |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 |
| 8 // |
| 9 // Unless required by applicable law or agreed to in writing, software |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 12 // See the License for the specific language governing permissions and |
| 13 // limitations under the License. |
| 14 |
| 15 |
| 16 (function(shared, scope, testing) { |
| 17 var originalRequestAnimationFrame = window.requestAnimationFrame; |
| 18 var rafCallbacks = []; |
| 19 var rafId = 0; |
| 20 window.requestAnimationFrame = function(f) { |
| 21 var id = rafId++; |
| 22 if (rafCallbacks.length == 0 && !WEB_ANIMATIONS_TESTING) { |
| 23 originalRequestAnimationFrame(processRafCallbacks); |
| 24 } |
| 25 rafCallbacks.push([id, f]); |
| 26 return id; |
| 27 }; |
| 28 |
| 29 window.cancelAnimationFrame = function(id) { |
| 30 rafCallbacks.forEach(function(entry) { |
| 31 if (entry[0] == id) { |
| 32 entry[1] = function() {}; |
| 33 } |
| 34 }); |
| 35 }; |
| 36 |
| 37 function processRafCallbacks(t) { |
| 38 var processing = rafCallbacks; |
| 39 rafCallbacks = []; |
| 40 tick(t); |
| 41 processing.forEach(function(entry) { entry[1](t); }); |
| 42 if (needsRetick) |
| 43 tick(t); |
| 44 applyPendingEffects(); |
| 45 } |
| 46 |
| 47 function comparePlayers(leftPlayer, rightPlayer) { |
| 48 return leftPlayer._sequenceNumber - rightPlayer._sequenceNumber; |
| 49 } |
| 50 |
| 51 function InternalTimeline() { |
| 52 this._players = []; |
| 53 // Android 4.3 browser has window.performance, but not window.performance.no
w |
| 54 this.currentTime = window.performance && performance.now ? performance.now()
: 0; |
| 55 }; |
| 56 |
| 57 InternalTimeline.prototype = { |
| 58 _play: function(source) { |
| 59 source._timing = shared.normalizeTimingInput(source.timing); |
| 60 var player = new scope.Player(source); |
| 61 player._idle = false; |
| 62 player._timeline = this; |
| 63 this._players.push(player); |
| 64 scope.restart(); |
| 65 scope.invalidateEffects(); |
| 66 return player; |
| 67 } |
| 68 }; |
| 69 |
| 70 var ticking = false; |
| 71 var hasRestartedThisFrame = false; |
| 72 |
| 73 scope.restart = function() { |
| 74 if (!ticking) { |
| 75 ticking = true; |
| 76 requestAnimationFrame(function() {}); |
| 77 hasRestartedThisFrame = true; |
| 78 } |
| 79 return hasRestartedThisFrame; |
| 80 }; |
| 81 |
| 82 var needsRetick = false; |
| 83 scope.invalidateEffects = function() { |
| 84 needsRetick = true; |
| 85 }; |
| 86 |
| 87 var pendingEffects = []; |
| 88 function applyPendingEffects() { |
| 89 pendingEffects.forEach(function(f) { f(); }); |
| 90 } |
| 91 |
| 92 var originalGetComputedStyle = window.getComputedStyle; |
| 93 Object.defineProperty(window, 'getComputedStyle', { |
| 94 configurable: true, |
| 95 enumerable: true, |
| 96 value: function() { |
| 97 if (needsRetick) tick(timeline.currentTime); |
| 98 applyPendingEffects(); |
| 99 return originalGetComputedStyle.apply(this, arguments); |
| 100 }, |
| 101 }); |
| 102 |
| 103 function tick(t) { |
| 104 hasRestartedThisFrame = false; |
| 105 var timeline = scope.timeline; |
| 106 timeline.currentTime = t; |
| 107 timeline._players.sort(comparePlayers); |
| 108 ticking = false; |
| 109 var updatingPlayers = timeline._players; |
| 110 timeline._players = []; |
| 111 |
| 112 var newPendingClears = []; |
| 113 var newPendingEffects = []; |
| 114 updatingPlayers = updatingPlayers.filter(function(player) { |
| 115 player._inTimeline = player._tick(t); |
| 116 |
| 117 if (!player._inEffect) |
| 118 newPendingClears.push(player._source); |
| 119 else |
| 120 newPendingEffects.push(player._source); |
| 121 |
| 122 if (!player.finished && !player.paused && !player._idle) |
| 123 ticking = true; |
| 124 |
| 125 return player._inTimeline; |
| 126 }); |
| 127 |
| 128 pendingEffects.length = 0; |
| 129 pendingEffects.push.apply(pendingEffects, newPendingClears); |
| 130 pendingEffects.push.apply(pendingEffects, newPendingEffects); |
| 131 |
| 132 timeline._players.push.apply(timeline._players, updatingPlayers); |
| 133 needsRetick = false; |
| 134 |
| 135 if (ticking) |
| 136 requestAnimationFrame(function() {}); |
| 137 }; |
| 138 |
| 139 if (WEB_ANIMATIONS_TESTING) { |
| 140 testing.tick = processRafCallbacks; |
| 141 testing.isTicking = function() { return ticking; }; |
| 142 testing.setTicking = function(newVal) { ticking = newVal; }; |
| 143 } |
| 144 |
| 145 var timeline = new InternalTimeline(); |
| 146 scope.timeline = timeline; |
| 147 |
| 148 })(webAnimationsShared, webAnimations1, webAnimationsTesting); |
OLD | NEW |