智慧水务管理系统 - 精河县供水工程综合管理平台

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
  1. import clone from "../Core/clone.js";
  2. import Frozen from "../Core/Frozen.js";
  3. import defined from "../Core/defined.js";
  4. import DeveloperError from "../Core/DeveloperError.js";
  5. import EasingFunction from "../Core/EasingFunction.js";
  6. import getTimestamp from "../Core/getTimestamp.js";
  7. import TimeConstants from "../Core/TimeConstants.js";
  8. import { Tween as TweenJS } from "@tweenjs/tween.js";
  9. /**
  10. * A tween is an animation that interpolates the properties of two objects using an {@link EasingFunction}. Create
  11. * one using {@link Scene#tweens} and {@link TweenCollection#add} and related add functions.
  12. *
  13. * @alias Tween
  14. * @constructor
  15. *
  16. * @private
  17. */
  18. function Tween(
  19. tweens,
  20. tweenjs,
  21. startObject,
  22. stopObject,
  23. duration,
  24. delay,
  25. easingFunction,
  26. update,
  27. complete,
  28. cancel,
  29. ) {
  30. this._tweens = tweens;
  31. this._tweenjs = tweenjs;
  32. this._startObject = clone(startObject);
  33. this._stopObject = clone(stopObject);
  34. this._duration = duration;
  35. this._delay = delay;
  36. this._easingFunction = easingFunction;
  37. this._update = update;
  38. this._complete = complete;
  39. /**
  40. * The callback to call if the tween is canceled either because {@link Tween#cancelTween}
  41. * was called or because the tween was removed from the collection.
  42. *
  43. * @type {TweenCollection.TweenCancelledCallback}
  44. */
  45. this.cancel = cancel;
  46. /**
  47. * @private
  48. */
  49. this.needsStart = true;
  50. }
  51. Object.defineProperties(Tween.prototype, {
  52. /**
  53. * An object with properties for initial values of the tween. The properties of this object are changed during the tween's animation.
  54. * @memberof Tween.prototype
  55. *
  56. * @type {object}
  57. * @readonly
  58. */
  59. startObject: {
  60. get: function () {
  61. return this._startObject;
  62. },
  63. },
  64. /**
  65. * An object with properties for the final values of the tween.
  66. * @memberof Tween.prototype
  67. *
  68. * @type {object}
  69. * @readonly
  70. */
  71. stopObject: {
  72. get: function () {
  73. return this._stopObject;
  74. },
  75. },
  76. /**
  77. * The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
  78. * @memberof Tween.prototype
  79. *
  80. * @type {number}
  81. * @readonly
  82. */
  83. duration: {
  84. get: function () {
  85. return this._duration;
  86. },
  87. },
  88. /**
  89. * The delay, in seconds, before the tween starts animating.
  90. * @memberof Tween.prototype
  91. *
  92. * @type {number}
  93. * @readonly
  94. */
  95. delay: {
  96. get: function () {
  97. return this._delay;
  98. },
  99. },
  100. /**
  101. * Determines the curve for animtion.
  102. * @memberof Tween.prototype
  103. *
  104. * @type {EasingFunction}
  105. * @readonly
  106. */
  107. easingFunction: {
  108. get: function () {
  109. return this._easingFunction;
  110. },
  111. },
  112. /**
  113. * The callback to call at each animation update (usually tied to the a rendered frame).
  114. * @memberof Tween.prototype
  115. *
  116. * @type {TweenCollection.TweenUpdateCallback}
  117. * @readonly
  118. */
  119. update: {
  120. get: function () {
  121. return this._update;
  122. },
  123. },
  124. /**
  125. * The callback to call when the tween finishes animating.
  126. * @memberof Tween.prototype
  127. *
  128. * @type {TweenCollection.TweenCompleteCallback}
  129. * @readonly
  130. */
  131. complete: {
  132. get: function () {
  133. return this._complete;
  134. },
  135. },
  136. /**
  137. * @memberof Tween.prototype
  138. *
  139. * @private
  140. */
  141. tweenjs: {
  142. get: function () {
  143. return this._tweenjs;
  144. },
  145. },
  146. });
  147. /**
  148. * Cancels the tween calling the {@link Tween#cancel} callback if one exists. This
  149. * has no effect if the tween finished or was already canceled.
  150. */
  151. Tween.prototype.cancelTween = function () {
  152. this._tweens.remove(this);
  153. };
  154. /**
  155. * A collection of tweens for animating properties. Commonly accessed using {@link Scene#tweens}.
  156. *
  157. * @alias TweenCollection
  158. * @constructor
  159. *
  160. * @private
  161. */
  162. function TweenCollection() {
  163. this._tweens = [];
  164. }
  165. Object.defineProperties(TweenCollection.prototype, {
  166. /**
  167. * The number of tweens in the collection.
  168. * @memberof TweenCollection.prototype
  169. *
  170. * @type {number}
  171. * @readonly
  172. */
  173. length: {
  174. get: function () {
  175. return this._tweens.length;
  176. },
  177. },
  178. });
  179. /**
  180. * Creates a tween for animating between two sets of properties. The tween starts animating at the next call to {@link TweenCollection#update}, which
  181. * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
  182. *
  183. * @param {object} [options] Object with the following properties:
  184. * @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.
  185. * @param {object} options.stopObject An object with properties for the final values of the tween.
  186. * @param {number} options.duration The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
  187. * @param {number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
  188. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
  189. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
  190. * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating.
  191. * @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.
  192. * @returns {Tween} The tween.
  193. *
  194. * @exception {DeveloperError} options.duration must be positive.
  195. */
  196. TweenCollection.prototype.add = function (options) {
  197. options = options ?? Frozen.EMPTY_OBJECT;
  198. //>>includeStart('debug', pragmas.debug);
  199. if (!defined(options.startObject) || !defined(options.stopObject)) {
  200. throw new DeveloperError(
  201. "options.startObject and options.stopObject are required.",
  202. );
  203. }
  204. if (!defined(options.duration) || options.duration < 0.0) {
  205. throw new DeveloperError(
  206. "options.duration is required and must be positive.",
  207. );
  208. }
  209. //>>includeEnd('debug');
  210. if (options.duration === 0.0) {
  211. if (defined(options.complete)) {
  212. options.complete();
  213. }
  214. return new Tween(this);
  215. }
  216. const duration = options.duration / TimeConstants.SECONDS_PER_MILLISECOND;
  217. const delayInSeconds = options.delay ?? 0.0;
  218. const delay = delayInSeconds / TimeConstants.SECONDS_PER_MILLISECOND;
  219. const easingFunction = options.easingFunction ?? EasingFunction.LINEAR_NONE;
  220. const value = options.startObject;
  221. const tweenjs = new TweenJS(value);
  222. tweenjs.to(clone(options.stopObject), duration);
  223. tweenjs.delay(delay);
  224. tweenjs.easing(easingFunction);
  225. if (defined(options.update)) {
  226. tweenjs.onUpdate(function () {
  227. options.update(value);
  228. });
  229. }
  230. tweenjs.onComplete(options.complete ?? null);
  231. tweenjs.repeat(options._repeat ?? 0.0);
  232. const tween = new Tween(
  233. this,
  234. tweenjs,
  235. options.startObject,
  236. options.stopObject,
  237. options.duration,
  238. delayInSeconds,
  239. easingFunction,
  240. options.update,
  241. options.complete,
  242. options.cancel,
  243. );
  244. this._tweens.push(tween);
  245. return tween;
  246. };
  247. /**
  248. * 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
  249. * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
  250. *
  251. * @param {object} [options] Object with the following properties:
  252. * @param {object} options.object The object containing the property to animate.
  253. * @param {string} options.property The name of the property to animate.
  254. * @param {number} options.startValue The initial value.
  255. * @param {number} options.stopValue The final value.
  256. * @param {number} [options.duration=3.0] The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
  257. * @param {number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
  258. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
  259. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
  260. * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating.
  261. * @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.
  262. * @returns {Tween} The tween.
  263. *
  264. * @exception {DeveloperError} options.object must have the specified property.
  265. * @exception {DeveloperError} options.duration must be positive.
  266. */
  267. TweenCollection.prototype.addProperty = function (options) {
  268. options = options ?? Frozen.EMPTY_OBJECT;
  269. const object = options.object;
  270. const property = options.property;
  271. const startValue = options.startValue;
  272. const stopValue = options.stopValue;
  273. //>>includeStart('debug', pragmas.debug);
  274. if (!defined(object) || !defined(options.property)) {
  275. throw new DeveloperError(
  276. "options.object and options.property are required.",
  277. );
  278. }
  279. if (!defined(object[property])) {
  280. throw new DeveloperError(
  281. "options.object must have the specified property.",
  282. );
  283. }
  284. if (!defined(startValue) || !defined(stopValue)) {
  285. throw new DeveloperError(
  286. "options.startValue and options.stopValue are required.",
  287. );
  288. }
  289. //>>includeEnd('debug');
  290. function update(value) {
  291. object[property] = value.value;
  292. }
  293. return this.add({
  294. startObject: {
  295. value: startValue,
  296. },
  297. stopObject: {
  298. value: stopValue,
  299. },
  300. duration: options.duration ?? 3.0,
  301. delay: options.delay,
  302. easingFunction: options.easingFunction,
  303. update: update,
  304. complete: options.complete,
  305. cancel: options.cancel,
  306. _repeat: options._repeat,
  307. });
  308. };
  309. /**
  310. * 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
  311. * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
  312. *
  313. * @param {object} [options] Object with the following properties:
  314. * @param {Material} options.material The material to animate.
  315. * @param {number} [options.startValue=0.0] The initial alpha value.
  316. * @param {number} [options.stopValue=1.0] The final alpha value.
  317. * @param {number} [options.duration=3.0] The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
  318. * @param {number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
  319. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
  320. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
  321. * @param {TweenCollection.TweenCompleteCallback} [options.complete] The callback to call when the tween finishes animating.
  322. * @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.
  323. * @returns {Tween} The tween.
  324. *
  325. * @exception {DeveloperError} material has no properties with alpha components.
  326. * @exception {DeveloperError} options.duration must be positive.
  327. */
  328. TweenCollection.prototype.addAlpha = function (options) {
  329. options = options ?? Frozen.EMPTY_OBJECT;
  330. const material = options.material;
  331. //>>includeStart('debug', pragmas.debug);
  332. if (!defined(material)) {
  333. throw new DeveloperError("options.material is required.");
  334. }
  335. //>>includeEnd('debug');
  336. const properties = [];
  337. for (const property in material.uniforms) {
  338. if (
  339. material.uniforms.hasOwnProperty(property) &&
  340. defined(material.uniforms[property]) &&
  341. defined(material.uniforms[property].alpha)
  342. ) {
  343. properties.push(property);
  344. }
  345. }
  346. //>>includeStart('debug', pragmas.debug);
  347. if (properties.length === 0) {
  348. throw new DeveloperError(
  349. "material has no properties with alpha components.",
  350. );
  351. }
  352. //>>includeEnd('debug');
  353. function update(value) {
  354. const length = properties.length;
  355. for (let i = 0; i < length; ++i) {
  356. material.uniforms[properties[i]].alpha = value.alpha;
  357. }
  358. }
  359. return this.add({
  360. startObject: {
  361. alpha: options.startValue ?? 0.0, // Default to fade in
  362. },
  363. stopObject: {
  364. alpha: options.stopValue ?? 1.0,
  365. },
  366. duration: options.duration ?? 3.0,
  367. delay: options.delay,
  368. easingFunction: options.easingFunction,
  369. update: update,
  370. complete: options.complete,
  371. cancel: options.cancel,
  372. });
  373. };
  374. /**
  375. * 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
  376. * is implicit when {@link Viewer} or {@link CesiumWidget} render the scene.
  377. *
  378. * @param {object} [options] Object with the following properties:
  379. * @param {Material} options.material The material to animate.
  380. * @param {number} options.startValue The initial alpha value.
  381. * @param {number} options.stopValue The final alpha value.
  382. * @param {number} [options.duration=3.0] The duration, in seconds, for the tween. The tween is automatically removed from the collection when it stops.
  383. * @param {number} [options.delay=0.0] The delay, in seconds, before the tween starts animating.
  384. * @param {EasingFunction} [options.easingFunction=EasingFunction.LINEAR_NONE] Determines the curve for animtion.
  385. * @param {TweenCollection.TweenUpdateCallback} [options.update] The callback to call at each animation update (usually tied to the a rendered frame).
  386. * @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.
  387. * @returns {Tween} The tween.
  388. *
  389. * @exception {DeveloperError} material.uniforms must have an offset property.
  390. * @exception {DeveloperError} options.duration must be positive.
  391. */
  392. TweenCollection.prototype.addOffsetIncrement = function (options) {
  393. options = options ?? Frozen.EMPTY_OBJECT;
  394. const material = options.material;
  395. //>>includeStart('debug', pragmas.debug);
  396. if (!defined(material)) {
  397. throw new DeveloperError("material is required.");
  398. }
  399. if (!defined(material.uniforms.offset)) {
  400. throw new DeveloperError("material.uniforms must have an offset property.");
  401. }
  402. //>>includeEnd('debug');
  403. const uniforms = material.uniforms;
  404. return this.addProperty({
  405. object: uniforms,
  406. property: "offset",
  407. startValue: uniforms.offset,
  408. stopValue: uniforms.offset + 1,
  409. duration: options.duration,
  410. delay: options.delay,
  411. easingFunction: options.easingFunction,
  412. update: options.update,
  413. cancel: options.cancel,
  414. _repeat: Infinity,
  415. });
  416. };
  417. /**
  418. * Removes a tween from the collection.
  419. * <p>
  420. * This calls the {@link Tween#cancel} callback if the tween has one.
  421. * </p>
  422. *
  423. * @param {Tween} tween The tween to remove.
  424. * @returns {boolean} <code>true</code> if the tween was removed; <code>false</code> if the tween was not found in the collection.
  425. */
  426. TweenCollection.prototype.remove = function (tween) {
  427. if (!defined(tween)) {
  428. return false;
  429. }
  430. const index = this._tweens.indexOf(tween);
  431. if (index !== -1) {
  432. tween.tweenjs.stop();
  433. if (defined(tween.cancel)) {
  434. tween.cancel();
  435. }
  436. this._tweens.splice(index, 1);
  437. return true;
  438. }
  439. return false;
  440. };
  441. /**
  442. * Removes all tweens from the collection.
  443. * <p>
  444. * This calls the {@link Tween#cancel} callback for each tween that has one.
  445. * </p>
  446. */
  447. TweenCollection.prototype.removeAll = function () {
  448. const tweens = this._tweens;
  449. for (let i = 0; i < tweens.length; ++i) {
  450. const tween = tweens[i];
  451. tween.tweenjs.stop();
  452. if (defined(tween.cancel)) {
  453. tween.cancel();
  454. }
  455. }
  456. tweens.length = 0;
  457. };
  458. /**
  459. * Determines whether this collection contains a given tween.
  460. *
  461. * @param {Tween} tween The tween to check for.
  462. * @returns {boolean} <code>true</code> if this collection contains the tween, <code>false</code> otherwise.
  463. */
  464. TweenCollection.prototype.contains = function (tween) {
  465. return defined(tween) && this._tweens.indexOf(tween) !== -1;
  466. };
  467. /**
  468. * Returns the tween in the collection at the specified index. Indices are zero-based
  469. * and increase as tweens are added. Removing a tween shifts all tweens after
  470. * it to the left, changing their indices. This function is commonly used to iterate over
  471. * all the tween in the collection.
  472. *
  473. * @param {number} index The zero-based index of the tween.
  474. * @returns {Tween} The tween at the specified index.
  475. *
  476. * @example
  477. * // Output the duration of all the tweens in the collection.
  478. * const tweens = scene.tweens;
  479. * const length = tweens.length;
  480. * for (let i = 0; i < length; ++i) {
  481. * console.log(tweens.get(i).duration);
  482. * }
  483. */
  484. TweenCollection.prototype.get = function (index) {
  485. //>>includeStart('debug', pragmas.debug);
  486. if (!defined(index)) {
  487. throw new DeveloperError("index is required.");
  488. }
  489. //>>includeEnd('debug');
  490. return this._tweens[index];
  491. };
  492. /**
  493. * Updates the tweens in the collection to be at the provide time. When a tween finishes, it is removed
  494. * from the collection.
  495. *
  496. * @param {number} [time=getTimestamp()] The time in seconds. By default tweens are synced to the system clock.
  497. */
  498. TweenCollection.prototype.update = function (time) {
  499. const tweens = this._tweens;
  500. let i = 0;
  501. time = defined(time)
  502. ? time / TimeConstants.SECONDS_PER_MILLISECOND
  503. : getTimestamp();
  504. while (i < tweens.length) {
  505. const tween = tweens[i];
  506. const tweenjs = tween.tweenjs;
  507. if (tween.needsStart) {
  508. tween.needsStart = false;
  509. tweenjs.start(time);
  510. } else if (tweenjs.update(time)) {
  511. i++;
  512. } else {
  513. // there's a chance that the update callback has side effects that clear the list of tweens and/or adds new tweens
  514. // if it's the case that the update callback 1) clears all tweens held in the scene, then 2) adds new tweens
  515. // the splice operation below will not be operating on the original tween, but one of the unprocessed tweens added
  516. // from the update callback
  517. if (tweens[i]?.needsStart) {
  518. continue;
  519. }
  520. tweenjs.stop();
  521. tweens.splice(i, 1);
  522. }
  523. }
  524. };
  525. /**
  526. * A function that will execute when a tween completes.
  527. * @callback TweenCollection.TweenCompleteCallback
  528. */
  529. /**
  530. * A function that will execute when a tween updates.
  531. * @callback TweenCollection.TweenUpdateCallback
  532. */
  533. /**
  534. * A function that will execute when a tween is cancelled.
  535. * @callback TweenCollection.TweenCancelledCallback
  536. */
  537. export default TweenCollection;