123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588 |
- import clone from "../Core/clone.js";
- import defaultValue from "../Core/defaultValue.js";
- import defined from "../Core/defined.js";
- import DeveloperError from "../Core/DeveloperError.js";
- import EasingFunction from "../Core/EasingFunction.js";
- import getTimestamp from "../Core/getTimestamp.js";
- import TimeConstants from "../Core/TimeConstants.js";
- import TweenJS from "../ThirdParty/Tween.js";
- /**
- * A tween is an animation that interpolates the properties of two objects using an {@link EasingFunction}. Create
- * one using {@link Scene#tweens} and {@link TweenCollection#add} and related add functions.
- *
- * @alias Tween
- * @constructor
- *
- * @private
- */
- function Tween(
- tweens,
- tweenjs,
- startObject,
- stopObject,
- duration,
- delay,
- easingFunction,
- update,
- complete,
- cancel
- ) {
- this._tweens = tweens;
- this._tweenjs = tweenjs;
- this._startObject = clone(startObject);
- this._stopObject = clone(stopObject);
- this._duration = duration;
- this._delay = delay;
- this._easingFunction = easingFunction;
- this._update = update;
- this._complete = complete;
- /**
- * The callback to call if the tween is canceled either because {@link Tween#cancelTween}
- * was called or because the tween was removed from the collection.
- *
- * @type {TweenCollection.TweenCancelledCallback}
- */
- this.cancel = cancel;
- /**
- * @private
- */
- this.needsStart = true;
- }
- Object.defineProperties(Tween.prototype, {
- /**
- * An object with properties for initial values of the tween. The properties of this object are changed during the tween's animation.
- * @memberof Tween.prototype
- *
- * @type {Object}
- * @readonly
- */
- startObject: {
- get: function () {
- return this._startObject;
- },
- },
- /**
- * An object with properties for the final values of the tween.
- * @memberof Tween.prototype
- *
- * @type {Object}
- * @readonly
- */
- stopObject: {
- get: function () {
- return this._stopObject;
- },
- },
- /**
- * The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
- * @memberof Tween.prototype
- *
- * @type {Number}
- * @readonly
- */
- duration: {
- get: function () {
- return this._duration;
- },
- },
- /**
- * The delay, in seconds, before the tween starts animating.
- * @memberof Tween.prototype
- *
- * @type {Number}
- * @readonly
- */
- delay: {
- get: function () {
- return this._delay;
- },
- },
- /**
- * Determines the curve for animtion.
- * @memberof Tween.prototype
- *
- * @type {EasingFunction}
- * @readonly
- */
- easingFunction: {
- get: function () {
- return this._easingFunction;
- },
- },
- /**
- * The callback to call at each animation update (usually tied to the a rendered frame).
- * @memberof Tween.prototype
- *
- * @type {TweenCollection.TweenUpdateCallback}
- * @readonly
- */
- update: {
- get: function () {
- return this._update;
- },
- },
- /**
- * The callback to call when the tween finishes animating.
- * @memberof Tween.prototype
- *
- * @type {TweenCollection.TweenCompleteCallback}
- * @readonly
- */
- complete: {
- get: function () {
- return this._complete;
- },
- },
- /**
- * @memberof Tween.prototype
- *
- * @private
- */
- tweenjs: {
- get: function () {
- return this._tweenjs;
- },
- },
- });
- /**
- * Cancels the tween calling the {@link Tween#cancel} callback if one exists. This
- * has no effect if the tween finished or was already canceled.
- */
- Tween.prototype.cancelTween = function () {
- this._tweens.remove(this);
- };
- /**
- * A collection of tweens for animating properties. Commonly accessed using {@link Scene#tweens}.
- *
- * @alias TweenCollection
- * @constructor
- *
- * @private
- */
- function TweenCollection() {
- this._tweens = [];
- }
- Object.defineProperties(TweenCollection.prototype, {
- /**
- * The number of tweens in the collection.
- * @memberof TweenCollection.prototype
- *
- * @type {Number}
- * @readonly
- */
- length: {
- get: function () {
- return this._tweens.length;
- },
- },
- });
- /**
- * Creates a tween for animating between two sets of properties. The tween starts animating at the next call to {@link TweenCollection#update}, which
- * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {Object} options.startObject An object with properties for initial values of the tween. The properties of this object are changed during the tween's animation.
- * @param {Object} options.stopObject An object with properties for the final values of the tween.
- * @param {Number} options.duration The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
- * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
- * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
- * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
- * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating.
- * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection.
- * @returns {Tween} The tween.
- *
- * @exception {DeveloperError} options.duration must be positive.
- */
- TweenCollection.prototype.add = function (options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- //>>includeStart('debug', pragmas.debug);
- if (!defined(options.startObject) || !defined(options.stopObject)) {
- throw new DeveloperError(
- "options.startObject and options.stopObject are required."
- );
- }
- if (!defined(options.duration) || options.duration < 0.0) {
- throw new DeveloperError(
- "options.duration is required and must be positive."
- );
- }
- //>>includeEnd('debug');
- if (options.duration === 0.0) {
- if (defined(options.complete)) {
- options.complete();
- }
- return new Tween(this);
- }
- const duration = options.duration / TimeConstants.SECONDS_PER_MILLISECOND;
- const delayInSeconds = defaultValue(options.delay, 0.0);
- const delay = delayInSeconds / TimeConstants.SECONDS_PER_MILLISECOND;
- const easingFunction = defaultValue(
- options.easingFunction,
- EasingFunction.LINEAR_NONE
- );
- const value = options.startObject;
- const tweenjs = new TweenJS.Tween(value);
- tweenjs.to(clone(options.stopObject), duration);
- tweenjs.delay(delay);
- tweenjs.easing(easingFunction);
- if (defined(options.update)) {
- tweenjs.onUpdate(function () {
- options.update(value);
- });
- }
- tweenjs.onComplete(defaultValue(options.complete, null));
- tweenjs.repeat(defaultValue(options._repeat, 0.0));
- const tween = new Tween(
- this,
- tweenjs,
- options.startObject,
- options.stopObject,
- options.duration,
- delayInSeconds,
- easingFunction,
- options.update,
- options.complete,
- options.cancel
- );
- this._tweens.push(tween);
- return tween;
- };
- /**
- * Creates a tween for animating a scalar property on the given object. The tween starts animating at the next call to {@link TweenCollection#update}, which
- * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {Object} options.object The object containing the property to animate.
- * @param {String} options.property The name of the property to animate.
- * @param {Number} options.startValue The initial value.
- * @param {Number} options.stopValue The final value.
- * @param {Number} [options.duration=3.0] The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
- * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
- * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
- * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
- * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating.
- * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection.
- * @returns {Tween} The tween.
- *
- * @exception {DeveloperError} options.object must have the specified property.
- * @exception {DeveloperError} options.duration must be positive.
- */
- TweenCollection.prototype.addProperty = function (options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const object = options.object;
- const property = options.property;
- const startValue = options.startValue;
- const stopValue = options.stopValue;
- //>>includeStart('debug', pragmas.debug);
- if (!defined(object) || !defined(options.property)) {
- throw new DeveloperError(
- "options.object and options.property are required."
- );
- }
- if (!defined(object[property])) {
- throw new DeveloperError(
- "options.object must have the specified property."
- );
- }
- if (!defined(startValue) || !defined(stopValue)) {
- throw new DeveloperError(
- "options.startValue and options.stopValue are required."
- );
- }
- //>>includeEnd('debug');
- function update(value) {
- object[property] = value.value;
- }
- return this.add({
- startObject: {
- value: startValue,
- },
- stopObject: {
- value: stopValue,
- },
- duration: defaultValue(options.duration, 3.0),
- delay: options.delay,
- easingFunction: options.easingFunction,
- update: update,
- complete: options.complete,
- cancel: options.cancel,
- _repeat: options._repeat,
- });
- };
- /**
- * Creates a tween for animating the alpha of all color uniforms on a {@link Material}. The tween starts animating at the next call to {@link TweenCollection#update}, which
- * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {Material} options.material The material to animate.
- * @param {Number} [options.startValue=0.0] The initial alpha value.
- * @param {Number} [options.stopValue=1.0] The final alpha value.
- * @param {Number} [options.duration=3.0] The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
- * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
- * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
- * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
- * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating.
- * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection.
- * @returns {Tween} The tween.
- *
- * @exception {DeveloperError} material has no properties with alpha components.
- * @exception {DeveloperError} options.duration must be positive.
- */
- TweenCollection.prototype.addAlpha = function (options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const material = options.material;
- //>>includeStart('debug', pragmas.debug);
- if (!defined(material)) {
- throw new DeveloperError("options.material is required.");
- }
- //>>includeEnd('debug');
- const properties = [];
- for (const property in material.uniforms) {
- if (
- material.uniforms.hasOwnProperty(property) &&
- defined(material.uniforms[property]) &&
- defined(material.uniforms[property].alpha)
- ) {
- properties.push(property);
- }
- }
- //>>includeStart('debug', pragmas.debug);
- if (properties.length === 0) {
- throw new DeveloperError(
- "material has no properties with alpha components."
- );
- }
- //>>includeEnd('debug');
- function update(value) {
- const length = properties.length;
- for (let i = 0; i < length; ++i) {
- material.uniforms[properties[i]].alpha = value.alpha;
- }
- }
- return this.add({
- startObject: {
- alpha: defaultValue(options.startValue, 0.0), // Default to fade in
- },
- stopObject: {
- alpha: defaultValue(options.stopValue, 1.0),
- },
- duration: defaultValue(options.duration, 3.0),
- delay: options.delay,
- easingFunction: options.easingFunction,
- update: update,
- complete: options.complete,
- cancel: options.cancel,
- });
- };
- /**
- * Creates a tween for animating the offset uniform of a {@link Material}. The tween starts animating at the next call to {@link TweenCollection#update}, which
- * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
- *
- * @param {Object} [options] Object with the following properties:
- * @param {Material} options.material The material to animate.
- * @param {Number} options.startValue The initial alpha value.
- * @param {Number} options.stopValue The final alpha value.
- * @param {Number} [options.duration=3.0] The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
- * @param {Number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
- * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
- * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
- * @param {TweenCollection.TweenCancelledCallback} [options.cancel] The callback to call if the tween is canceled either because {@link Tween#cancelTween} was called or because the tween was removed from the collection.
- * @returns {Tween} The tween.
- *
- * @exception {DeveloperError} material.uniforms must have an offset property.
- * @exception {DeveloperError} options.duration must be positive.
- */
- TweenCollection.prototype.addOffsetIncrement = function (options) {
- options = defaultValue(options, defaultValue.EMPTY_OBJECT);
- const material = options.material;
- //>>includeStart('debug', pragmas.debug);
- if (!defined(material)) {
- throw new DeveloperError("material is required.");
- }
- if (!defined(material.uniforms.offset)) {
- throw new DeveloperError("material.uniforms must have an offset property.");
- }
- //>>includeEnd('debug');
- const uniforms = material.uniforms;
- return this.addProperty({
- object: uniforms,
- property: "offset",
- startValue: uniforms.offset,
- stopValue: uniforms.offset + 1,
- duration: options.duration,
- delay: options.delay,
- easingFunction: options.easingFunction,
- update: options.update,
- cancel: options.cancel,
- _repeat: Infinity,
- });
- };
- /**
- * Removes a tween from the collection.
- * <p>
- * This calls the {@link Tween#cancel} callback if the tween has one.
- * </p>
- *
- * @param {Tween} tween The tween to remove.
- * @returns {Boolean} <code>true</code> if the tween was removed; <code>false</code> if the tween was not found in the collection.
- */
- TweenCollection.prototype.remove = function (tween) {
- if (!defined(tween)) {
- return false;
- }
- const index = this._tweens.indexOf(tween);
- if (index !== -1) {
- tween.tweenjs.stop();
- if (defined(tween.cancel)) {
- tween.cancel();
- }
- this._tweens.splice(index, 1);
- return true;
- }
- return false;
- };
- /**
- * Removes all tweens from the collection.
- * <p>
- * This calls the {@link Tween#cancel} callback for each tween that has one.
- * </p>
- */
- TweenCollection.prototype.removeAll = function () {
- const tweens = this._tweens;
- for (let i = 0; i < tweens.length; ++i) {
- const tween = tweens[i];
- tween.tweenjs.stop();
- if (defined(tween.cancel)) {
- tween.cancel();
- }
- }
- tweens.length = 0;
- };
- /**
- * Determines whether this collection contains a given tween.
- *
- * @param {Tween} tween The tween to check for.
- * @returns {Boolean} <code>true</code> if this collection contains the tween, <code>false</code> otherwise.
- */
- TweenCollection.prototype.contains = function (tween) {
- return defined(tween) && this._tweens.indexOf(tween) !== -1;
- };
- /**
- * Returns the tween in the collection at the specified index. Indices are zero-based
- * and increase as tweens are added. Removing a tween shifts all tweens after
- * it to the left, changing their indices. This function is commonly used to iterate over
- * all the tween in the collection.
- *
- * @param {Number} index The zero-based index of the tween.
- * @returns {Tween} The tween at the specified index.
- *
- * @example
- * // Output the duration of all the tweens in the collection.
- * const tweens = scene.tweens;
- * const length = tweens.length;
- * for (let i = 0; i < length; ++i) {
- * console.log(tweens.get(i).duration);
- * }
- */
- TweenCollection.prototype.get = function (index) {
- //>>includeStart('debug', pragmas.debug);
- if (!defined(index)) {
- throw new DeveloperError("index is required.");
- }
- //>>includeEnd('debug');
- return this._tweens[index];
- };
- /**
- * Updates the tweens in the collection to be at the provide time. When a tween finishes, it is removed
- * from the collection.
- *
- * @param {Number} [time=getTimestamp()] The time in seconds. By default tweens are synced to the system clock.
- */
- TweenCollection.prototype.update = function (time) {
- const tweens = this._tweens;
- let i = 0;
- time = defined(time)
- ? time / TimeConstants.SECONDS_PER_MILLISECOND
- : getTimestamp();
- while (i < tweens.length) {
- const tween = tweens[i];
- const tweenjs = tween.tweenjs;
- if (tween.needsStart) {
- tween.needsStart = false;
- tweenjs.start(time);
- } else if (tweenjs.update(time)) {
- i++;
- } else {
- tweenjs.stop();
- tweens.splice(i, 1);
- }
- }
- };
- /**
- * A function that will execute when a tween completes.
- * @callback TweenCollection.TweenCompleteCallback
- */
- /**
- * A function that will execute when a tween updates.
- * @callback TweenCollection.TweenUpdateCallback
- */
- /**
- * A function that will execute when a tween is cancelled.
- * @callback TweenCollection.TweenCancelledCallback
- */
- export default TweenCollection;
|