• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<!DOCTYPE html>
2<!--
3Copyright (c) 2014 The Chromium Authors. All rights reserved.
4Use of this source code is governed by a BSD-style license that can be
5found in the LICENSE file.
6-->
7<link rel="import" href="/tracing/base/event_target.html">
8<link rel="import" href="/tracing/base/raf.html">
9<link rel="import" href="/tracing/ui/base/animation.html">
10<script>
11'use strict';
12
13tr.exportTo('tr.ui.b', function() {
14  /**
15   * Manages execution, queueing and blending of tr.ui.b.Animations against
16   * a single target.
17   *
18   * Targets must have a cloneAnimationState() method that returns all the
19   * animatable states of that target.
20   *
21   * @constructor
22   * @extends {tr.b.EventTarget}
23   */
24  function AnimationController() {
25    tr.b.EventTarget.call(this);
26
27    this.target_ = undefined;
28
29    this.activeAnimation_ = undefined;
30
31    this.tickScheduled_ = false;
32  }
33
34  AnimationController.prototype = {
35    __proto__: tr.b.EventTarget.prototype,
36
37    get target() {
38      return this.target_;
39    },
40
41    set target(target) {
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');
47
48      this.target_ = target;
49    },
50
51    get activeAnimation() {
52      return this.activeAnimation_;
53    },
54
55    get hasActiveAnimation() {
56      return !!this.activeAnimation_;
57    },
58
59    queueAnimation: function(animation, opt_now) {
60      if (this.target_ === undefined)
61        throw new Error('Cannot queue animations without a target');
62
63      var now;
64      if (opt_now !== undefined)
65        now = opt_now;
66      else
67        now = window.performance.now();
68
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
72        // point.
73        var done = this.activeAnimation_.tick(now, this.target_);
74        if (done)
75          this.activeAnimation_ = undefined;
76      }
77
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_);
82        } else {
83          this.activeAnimation_.didStopEarly(now, this.target_, false);
84        }
85      }
86      this.activeAnimation_ = animation;
87      this.activeAnimation_.start(now, this.target_);
88
89      if (this.tickScheduled_)
90        return;
91      this.tickScheduled_ = true;
92      tr.b.requestAnimationFrame(this.tickActiveAnimation_, this);
93    },
94
95    cancelActiveAnimation: function(opt_now) {
96      if (!this.activeAnimation_)
97        return;
98      var now;
99      if (opt_now !== undefined)
100        now = opt_now;
101      else
102        now = window.performance.now();
103      this.activeAnimation_.didStopEarly(now, this.target_, false);
104      this.activeAnimation_ = undefined;
105    },
106
107    tickActiveAnimation_: function(frameBeginTime) {
108      this.tickScheduled_ = false;
109      if (!this.activeAnimation_)
110        return;
111
112      if (this.target_ === undefined) {
113        this.activeAnimation_.didStopEarly(frameBeginTime, this.target_, false);
114        return;
115      }
116
117      var oldTargetState = this.target_.cloneAnimationState();
118
119      var done = this.activeAnimation_.tick(frameBeginTime, this.target_);
120      if (done)
121        this.activeAnimation_ = undefined;
122
123      if (this.activeAnimation_) {
124        this.tickScheduled_ = true;
125        tr.b.requestAnimationFrame(this.tickActiveAnimation_, this);
126      }
127
128      if (oldTargetState) {
129        var e = new tr.b.Event('didtick');
130        e.oldTargetState = oldTargetState;
131        this.dispatchEvent(e, false, false);
132      }
133    }
134  };
135
136  return {
137    AnimationController: AnimationController
138  };
139});
140</script>
141