3 Copyright (c) 2014 The Chromium Authors. All rights reserved.
4 Use of this source code is governed by a BSD-style license that can be
5 found in the LICENSE file.
7 <link rel="import" href="/base/event_target.html">
8 <link rel="import" href="/base/raf.html">
9 <link rel="import" href="/base/ui/animation.html">
13 tv.exportTo('tv.ui', function() {
15 * Manages execution, queueing and blending of tv.ui.Animations against
18 * Targets must have a cloneAnimationState() method that returns all the
19 * animatable states of that target.
22 * @extends {tv.EventTarget}
24 function AnimationController() {
25 tv.EventTarget.call(this);
27 this.target_ = undefined;
29 this.activeAnimation_ = undefined;
31 this.tickScheduled_ = false;
34 AnimationController.prototype = {
35 __proto__: tv.EventTarget.prototype,
42 if (this.activeAnimation_)
43 throw new Error('Cannot change target while animation is running.');
44 if (target.cloneAnimationState === undefined ||
45 typeof target.cloneAnimationState !== 'function')
46 throw new Error('target must have a cloneAnimationState function');
48 this.target_ = target;
51 get activeAnimation() {
52 return this.activeAnimation_;
55 get hasActiveAnimation() {
56 return !!this.activeAnimation_;
59 queueAnimation: function(animation, opt_now) {
60 if (this.target_ === undefined)
61 throw new Error('Cannot queue animations without a target');
64 if (opt_now !== undefined)
67 now = window.performance.now();
69 if (this.activeAnimation_) {
70 // Must tick the animation before stopping it case its about to stop,
71 // and to update the target with its final sets of edits up to this
73 var done = this.activeAnimation_.tick(now, this.target_);
75 this.activeAnimation_ = undefined;
78 if (this.activeAnimation_) {
79 if (animation.canTakeOverFor(this.activeAnimation_)) {
80 this.activeAnimation_.didStopEarly(now, this.target_, true);
81 animation.takeOverFor(this.activeAnimation_, now, this.target_);
83 this.activeAnimation_.didStopEarly(now, this.target_, false);
86 this.activeAnimation_ = animation;
87 this.activeAnimation_.start(now, this.target_);
89 if (this.tickScheduled_)
91 this.tickScheduled_ = true;
92 tv.requestAnimationFrame(this.tickActiveAnimation_, this);
95 cancelActiveAnimation: function(opt_now) {
96 if (!this.activeAnimation_)
99 if (opt_now !== undefined)
102 now = window.performance.now();
103 this.activeAnimation_.didStopEarly(now, this.target_, false);
104 this.activeAnimation_ = undefined;
107 tickActiveAnimation_: function(frameBeginTime) {
108 this.tickScheduled_ = false;
109 if (!this.activeAnimation_)
112 if (this.target_ === undefined) {
113 this.activeAnimation_.didStopEarly(frameBeginTime, this.target_, false);
117 var oldTargetState = this.target_.cloneAnimationState();
119 var done = this.activeAnimation_.tick(frameBeginTime, this.target_);
121 this.activeAnimation_ = undefined;
123 if (this.activeAnimation_) {
124 this.tickScheduled_ = true;
125 tv.requestAnimationFrame(this.tickActiveAnimation_, this);
128 if (oldTargetState) {
129 var e = new Event('didtick');
130 e.oldTargetState = oldTargetState;
131 this.dispatchEvent(e, false, false);
137 AnimationController: AnimationController