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(function(shared, scope, testing) { 15 16 var nullTarget = document.createElementNS('http://www.w3.org/1999/xhtml', 'div'); 17 18 var sequenceNumber = 0; 19 scope.bindAnimationForCustomEffect = function(animation) { 20 var target = animation.effect.target; 21 var effectFunction; 22 var isKeyframeEffect = typeof animation.effect.getFrames() == 'function'; 23 if (isKeyframeEffect) { 24 effectFunction = animation.effect.getFrames(); 25 } else { 26 effectFunction = animation.effect._onsample; 27 } 28 var timing = animation.effect.timing; 29 var last = null; 30 timing = shared.normalizeTimingInput(timing); 31 var callback = function() { 32 var t = callback._animation ? callback._animation.currentTime : null; 33 if (t !== null) { 34 t = shared.calculateIterationProgress(shared.calculateActiveDuration(timing), t, timing); 35 if (isNaN(t)) 36 t = null; 37 } 38 // FIXME: There are actually more conditions under which the effectFunction 39 // should be called. 40 if (t !== last) { 41 if (isKeyframeEffect) { 42 effectFunction(t, target, animation.effect); 43 } else { 44 effectFunction(t, animation.effect, animation.effect._animation); 45 } 46 } 47 last = t; 48 }; 49 50 callback._animation = animation; 51 callback._registered = false; 52 callback._sequenceNumber = sequenceNumber++; 53 animation._callback = callback; 54 register(callback); 55 }; 56 57 var callbacks = []; 58 var ticking = false; 59 function register(callback) { 60 if (callback._registered) 61 return; 62 callback._registered = true; 63 callbacks.push(callback); 64 if (!ticking) { 65 ticking = true; 66 requestAnimationFrame(tick); 67 } 68 } 69 70 function tick(t) { 71 var updating = callbacks; 72 callbacks = []; 73 updating.sort(function(left, right) { 74 return left._sequenceNumber - right._sequenceNumber; 75 }); 76 updating = updating.filter(function(callback) { 77 callback(); 78 var playState = callback._animation ? callback._animation.playState : 'idle'; 79 if (playState != 'running' && playState != 'pending') 80 callback._registered = false; 81 return callback._registered; 82 }); 83 callbacks.push.apply(callbacks, updating); 84 85 if (callbacks.length) { 86 ticking = true; 87 requestAnimationFrame(tick); 88 } else { 89 ticking = false; 90 } 91 } 92 93 scope.Animation.prototype._register = function() { 94 if (this._callback) 95 register(this._callback); 96 }; 97 98})(webAnimationsShared, webAnimationsNext, webAnimationsTesting); 99