UNPKG

@nativescript/core

Version:

A JavaScript library providing an easy to use api for interacting with iOS and Android platform APIs.

240 lines • 10.3 kB
// Requires. import { Color } from '../../color'; import { Trace } from '../../trace'; import { PercentLength } from '../styling/style-properties'; export * from './animation-interfaces'; export var Properties; (function (Properties) { Properties.opacity = 'opacity'; Properties.backgroundColor = 'backgroundColor'; Properties.translate = 'translate'; Properties.rotate = 'rotate'; Properties.scale = 'scale'; Properties.height = 'height'; Properties.width = 'width'; })(Properties || (Properties = {})); export class AnimationBase { constructor(animationDefinitions, playSequentially) { if (!animationDefinitions || animationDefinitions.length === 0) { console.error('No animation definitions specified'); return; } if (Trace.isEnabled()) { Trace.write('Analyzing ' + animationDefinitions.length + ' animation definitions...', Trace.categories.Animation); } this._propertyAnimations = new Array(); for (let i = 0, length = animationDefinitions.length; i < length; i++) { if (animationDefinitions[i].curve) { animationDefinitions[i].curve = this._resolveAnimationCurve(animationDefinitions[i].curve); } this._propertyAnimations = this._propertyAnimations.concat(AnimationBase._createPropertyAnimations(animationDefinitions[i])); } if (this._propertyAnimations.length === 0) { if (Trace.isEnabled()) { Trace.write('Nothing to animate.', Trace.categories.Animation); } return; } if (Trace.isEnabled()) { Trace.write('Created ' + this._propertyAnimations.length + ' individual property animations.', Trace.categories.Animation); } this._playSequentially = playSequentially; } _rejectAlreadyPlaying() { const reason = 'Animation is already playing.'; Trace.write(reason, Trace.categories.Animation, Trace.messageType.warn); return new Promise((resolve, reject) => { reject(reason); }); } play() { // We have to actually create a "Promise" due to a bug in the v8 engine and decedent promises // We just cast it to a animationPromise so that all the rest of the code works fine const animationFinishedPromise = new Promise((resolve, reject) => { this._resolve = resolve; this._reject = reject; }); this.fixupAnimationPromise(animationFinishedPromise); this._isPlaying = true; return animationFinishedPromise; } fixupAnimationPromise(promise) { // Since we are using function() below because of arguments, TS won't automatically do a _this for those functions. const _this = this; promise.cancel = () => { _this.cancel(); }; const _then = promise.then; promise.then = function () { // eslint-disable-next-line prefer-rest-params const r = _then.apply(promise, arguments); _this.fixupAnimationPromise(r); return r; }; const _catch = promise.catch; promise.catch = function () { // eslint-disable-next-line prefer-rest-params const r = _catch.apply(promise, arguments); _this.fixupAnimationPromise(r); return r; }; } cancel() { // Implemented in platform specific files } get isPlaying() { return this._isPlaying; } _resolveAnimationFinishedPromise() { this._isPlaying = false; this._resolve(); } _rejectAnimationFinishedPromise() { this._isPlaying = false; this._reject(new Error('Animation cancelled.')); } static _createPropertyAnimations(animationDefinition) { if (!animationDefinition.target) { console.error('No animation target specified.'); return; } for (const item in animationDefinition) { const value = animationDefinition[item]; if (value === undefined) { continue; } if ((item === Properties.opacity || item === 'duration' || item === 'delay' || item === 'iterations') && typeof value !== 'number') { console.error(`Property ${item} must be valid number. Value: ${value}`); return; } else if ((item === Properties.scale || item === Properties.translate) && (typeof value.x !== 'number' || typeof value.y !== 'number')) { console.error(`Property ${item} must be valid Pair. Value: ${value}`); return; } else if (item === Properties.backgroundColor && !Color.isValid(animationDefinition.backgroundColor)) { console.error(`Property ${item} must be valid color. Value: ${value}`); return; } else if (item === Properties.width || item === Properties.height) { // Coerce input into a PercentLength object in case it's a string. animationDefinition[item] = PercentLength.parse(value); } else if (item === Properties.rotate) { const rotate = value; if (typeof rotate !== 'number' && !(typeof rotate.x === 'number' && typeof rotate.y === 'number' && typeof rotate.z === 'number')) { console.error(`Property ${rotate} must be valid number or Point3D. Value: ${value}`); return; } } } const propertyAnimations = new Array(); // opacity if (animationDefinition.opacity !== undefined) { propertyAnimations.push({ target: animationDefinition.target, property: Properties.opacity, value: animationDefinition.opacity, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } // backgroundColor if (animationDefinition.backgroundColor !== undefined) { propertyAnimations.push({ target: animationDefinition.target, property: Properties.backgroundColor, value: typeof animationDefinition.backgroundColor === 'string' ? new Color(animationDefinition.backgroundColor) : animationDefinition.backgroundColor, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } // translate if (animationDefinition.translate !== undefined) { propertyAnimations.push({ target: animationDefinition.target, property: Properties.translate, value: animationDefinition.translate, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } // scale if (animationDefinition.scale !== undefined) { propertyAnimations.push({ target: animationDefinition.target, property: Properties.scale, value: animationDefinition.scale, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } // rotate if (animationDefinition.rotate !== undefined) { // Make sure the value of the rotation property is always Point3D let rotationValue; if (typeof animationDefinition.rotate === 'number') { rotationValue = { x: 0, y: 0, z: animationDefinition.rotate }; } else { rotationValue = animationDefinition.rotate; } propertyAnimations.push({ target: animationDefinition.target, property: Properties.rotate, value: rotationValue, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } // height if (animationDefinition.height !== undefined) { propertyAnimations.push({ target: animationDefinition.target, property: Properties.height, value: animationDefinition.height, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } // width if (animationDefinition.width !== undefined) { propertyAnimations.push({ target: animationDefinition.target, property: Properties.width, value: animationDefinition.width, duration: animationDefinition.duration, delay: animationDefinition.delay, iterations: animationDefinition.iterations, curve: animationDefinition.curve, }); } if (propertyAnimations.length === 0) { console.error('No known animation properties specified'); } return propertyAnimations; } static _getAnimationInfo(animation) { return JSON.stringify({ target: animation.target.id, property: animation.property, value: animation.value, duration: animation.duration, delay: animation.delay, iterations: animation.iterations, curve: animation.curve, }); } } //# sourceMappingURL=animation-common.js.map