1 |
|
2 | import { Color } from '../../color';
|
3 | import { Trace } from '../../trace';
|
4 | import { PercentLength } from '../styling/style-properties';
|
5 | export * from './animation-interfaces';
|
6 | export var Properties;
|
7 | (function (Properties) {
|
8 | Properties.opacity = 'opacity';
|
9 | Properties.backgroundColor = 'backgroundColor';
|
10 | Properties.translate = 'translate';
|
11 | Properties.rotate = 'rotate';
|
12 | Properties.scale = 'scale';
|
13 | Properties.height = 'height';
|
14 | Properties.width = 'width';
|
15 | })(Properties || (Properties = {}));
|
16 | export class CubicBezierAnimationCurve {
|
17 | constructor(x1, y1, x2, y2) {
|
18 | this.x1 = x1;
|
19 | this.y1 = y1;
|
20 | this.x2 = x2;
|
21 | this.y2 = y2;
|
22 | }
|
23 | }
|
24 | export class AnimationBase {
|
25 | constructor(animationDefinitions, playSequentially) {
|
26 | if (!animationDefinitions || animationDefinitions.length === 0) {
|
27 | console.error('No animation definitions specified');
|
28 | return;
|
29 | }
|
30 | if (Trace.isEnabled()) {
|
31 | Trace.write('Analyzing ' + animationDefinitions.length + ' animation definitions...', Trace.categories.Animation);
|
32 | }
|
33 | this._propertyAnimations = new Array();
|
34 | for (let i = 0, length = animationDefinitions.length; i < length; i++) {
|
35 | if (animationDefinitions[i].curve) {
|
36 | animationDefinitions[i].curve = this._resolveAnimationCurve(animationDefinitions[i].curve);
|
37 | }
|
38 | this._propertyAnimations = this._propertyAnimations.concat(AnimationBase._createPropertyAnimations(animationDefinitions[i]));
|
39 | }
|
40 | if (this._propertyAnimations.length === 0) {
|
41 | if (Trace.isEnabled()) {
|
42 | Trace.write('Nothing to animate.', Trace.categories.Animation);
|
43 | }
|
44 | return;
|
45 | }
|
46 | if (Trace.isEnabled()) {
|
47 | Trace.write('Created ' + this._propertyAnimations.length + ' individual property animations.', Trace.categories.Animation);
|
48 | }
|
49 | this._playSequentially = playSequentially;
|
50 | }
|
51 | _rejectAlreadyPlaying() {
|
52 | const reason = 'Animation is already playing.';
|
53 | Trace.write(reason, Trace.categories.Animation, Trace.messageType.warn);
|
54 | return new Promise((resolve, reject) => {
|
55 | reject(reason);
|
56 | });
|
57 | }
|
58 | play() {
|
59 |
|
60 |
|
61 | const animationFinishedPromise = new Promise((resolve, reject) => {
|
62 | this._resolve = resolve;
|
63 | this._reject = reject;
|
64 | });
|
65 | this.fixupAnimationPromise(animationFinishedPromise);
|
66 | this._isPlaying = true;
|
67 | return animationFinishedPromise;
|
68 | }
|
69 | fixupAnimationPromise(promise) {
|
70 |
|
71 | const _this = this;
|
72 | promise.cancel = () => {
|
73 | _this.cancel();
|
74 | };
|
75 | const _then = promise.then;
|
76 | promise.then = function () {
|
77 |
|
78 | const r = _then.apply(promise, arguments);
|
79 | _this.fixupAnimationPromise(r);
|
80 | return r;
|
81 | };
|
82 | const _catch = promise.catch;
|
83 | promise.catch = function () {
|
84 |
|
85 | const r = _catch.apply(promise, arguments);
|
86 | _this.fixupAnimationPromise(r);
|
87 | return r;
|
88 | };
|
89 | }
|
90 | cancel() {
|
91 |
|
92 | }
|
93 | get isPlaying() {
|
94 | return this._isPlaying;
|
95 | }
|
96 | _resolveAnimationFinishedPromise() {
|
97 | this._isPlaying = false;
|
98 | this._resolve();
|
99 | }
|
100 | _rejectAnimationFinishedPromise() {
|
101 | this._isPlaying = false;
|
102 | this._reject(new Error('Animation cancelled.'));
|
103 | }
|
104 | static _createPropertyAnimations(animationDefinition) {
|
105 | if (!animationDefinition.target) {
|
106 | console.error('No animation target specified.');
|
107 | return;
|
108 | }
|
109 | for (const item in animationDefinition) {
|
110 | const value = animationDefinition[item];
|
111 | if (value === undefined) {
|
112 | continue;
|
113 | }
|
114 | if ((item === Properties.opacity || item === 'duration' || item === 'delay' || item === 'iterations') && typeof value !== 'number') {
|
115 | console.error(`Property ${item} must be valid number. Value: ${value}`);
|
116 | return;
|
117 | }
|
118 | else if ((item === Properties.scale || item === Properties.translate) && (typeof value.x !== 'number' || typeof value.y !== 'number')) {
|
119 | console.error(`Property ${item} must be valid Pair. Value: ${value}`);
|
120 | return;
|
121 | }
|
122 | else if (item === Properties.backgroundColor && !Color.isValid(animationDefinition.backgroundColor)) {
|
123 | console.error(`Property ${item} must be valid color. Value: ${value}`);
|
124 | return;
|
125 | }
|
126 | else if (item === Properties.width || item === Properties.height) {
|
127 |
|
128 | animationDefinition[item] = PercentLength.parse(value);
|
129 | }
|
130 | else if (item === Properties.rotate) {
|
131 | const rotate = value;
|
132 | if (typeof rotate !== 'number' && !(typeof rotate.x === 'number' && typeof rotate.y === 'number' && typeof rotate.z === 'number')) {
|
133 | console.error(`Property ${rotate} must be valid number or Point3D. Value: ${value}`);
|
134 | return;
|
135 | }
|
136 | }
|
137 | }
|
138 | const propertyAnimations = new Array();
|
139 |
|
140 | if (animationDefinition.opacity !== undefined) {
|
141 | propertyAnimations.push({
|
142 | target: animationDefinition.target,
|
143 | property: Properties.opacity,
|
144 | value: animationDefinition.opacity,
|
145 | duration: animationDefinition.duration,
|
146 | delay: animationDefinition.delay,
|
147 | iterations: animationDefinition.iterations,
|
148 | curve: animationDefinition.curve,
|
149 | });
|
150 | }
|
151 |
|
152 | if (animationDefinition.backgroundColor !== undefined) {
|
153 | propertyAnimations.push({
|
154 | target: animationDefinition.target,
|
155 | property: Properties.backgroundColor,
|
156 | value: typeof animationDefinition.backgroundColor === 'string' ? new Color(animationDefinition.backgroundColor) : animationDefinition.backgroundColor,
|
157 | duration: animationDefinition.duration,
|
158 | delay: animationDefinition.delay,
|
159 | iterations: animationDefinition.iterations,
|
160 | curve: animationDefinition.curve,
|
161 | });
|
162 | }
|
163 |
|
164 | if (animationDefinition.translate !== undefined) {
|
165 | propertyAnimations.push({
|
166 | target: animationDefinition.target,
|
167 | property: Properties.translate,
|
168 | value: animationDefinition.translate,
|
169 | duration: animationDefinition.duration,
|
170 | delay: animationDefinition.delay,
|
171 | iterations: animationDefinition.iterations,
|
172 | curve: animationDefinition.curve,
|
173 | });
|
174 | }
|
175 |
|
176 | if (animationDefinition.scale !== undefined) {
|
177 | propertyAnimations.push({
|
178 | target: animationDefinition.target,
|
179 | property: Properties.scale,
|
180 | value: animationDefinition.scale,
|
181 | duration: animationDefinition.duration,
|
182 | delay: animationDefinition.delay,
|
183 | iterations: animationDefinition.iterations,
|
184 | curve: animationDefinition.curve,
|
185 | });
|
186 | }
|
187 |
|
188 | if (animationDefinition.rotate !== undefined) {
|
189 |
|
190 | let rotationValue;
|
191 | if (typeof animationDefinition.rotate === 'number') {
|
192 | rotationValue = { x: 0, y: 0, z: animationDefinition.rotate };
|
193 | }
|
194 | else {
|
195 | rotationValue = animationDefinition.rotate;
|
196 | }
|
197 | propertyAnimations.push({
|
198 | target: animationDefinition.target,
|
199 | property: Properties.rotate,
|
200 | value: rotationValue,
|
201 | duration: animationDefinition.duration,
|
202 | delay: animationDefinition.delay,
|
203 | iterations: animationDefinition.iterations,
|
204 | curve: animationDefinition.curve,
|
205 | });
|
206 | }
|
207 |
|
208 | if (animationDefinition.height !== undefined) {
|
209 | propertyAnimations.push({
|
210 | target: animationDefinition.target,
|
211 | property: Properties.height,
|
212 | value: animationDefinition.height,
|
213 | duration: animationDefinition.duration,
|
214 | delay: animationDefinition.delay,
|
215 | iterations: animationDefinition.iterations,
|
216 | curve: animationDefinition.curve,
|
217 | });
|
218 | }
|
219 |
|
220 | if (animationDefinition.width !== undefined) {
|
221 | propertyAnimations.push({
|
222 | target: animationDefinition.target,
|
223 | property: Properties.width,
|
224 | value: animationDefinition.width,
|
225 | duration: animationDefinition.duration,
|
226 | delay: animationDefinition.delay,
|
227 | iterations: animationDefinition.iterations,
|
228 | curve: animationDefinition.curve,
|
229 | });
|
230 | }
|
231 | if (propertyAnimations.length === 0) {
|
232 | console.error('No known animation properties specified');
|
233 | }
|
234 | return propertyAnimations;
|
235 | }
|
236 | static _getAnimationInfo(animation) {
|
237 | return JSON.stringify({
|
238 | target: animation.target.id,
|
239 | property: animation.property,
|
240 | value: animation.value,
|
241 | duration: animation.duration,
|
242 | delay: animation.delay,
|
243 | iterations: animation.iterations,
|
244 | curve: animation.curve,
|
245 | });
|
246 | }
|
247 | }
|
248 |
|
\ | No newline at end of file |