KmlTour.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. import defined from "../Core/defined.js";
  2. import deprecationWarning from "../Core/deprecationWarning.js";
  3. import Event from "../Core/Event.js";
  4. /**
  5. * Describes a KmlTour, which uses KmlTourFlyTo, and KmlTourWait to
  6. * guide the camera to a specified destinations on given time intervals.
  7. *
  8. * @alias KmlTour
  9. * @constructor
  10. *
  11. * @param {string} name name parsed from KML
  12. * @param {string} id id parsed from KML
  13. * @param {Array} playlist array with KmlTourFlyTos and KmlTourWaits
  14. *
  15. * @see KmlTourFlyTo
  16. * @see KmlTourWait
  17. *
  18. * @demo {@link https://sandcastle.cesium.com/?src=KML%20Tours.html|KML Tours}
  19. */
  20. function KmlTour(name, id) {
  21. /**
  22. * Id of kml gx:Tour entry
  23. * @type {string}
  24. */
  25. this.id = id;
  26. /**
  27. * Tour name
  28. * @type {string}
  29. */
  30. this.name = name;
  31. /**
  32. * Index of current entry from playlist
  33. * @type {number}
  34. */
  35. this.playlistIndex = 0;
  36. /**
  37. * Array of playlist entries
  38. * @type {Array}
  39. */
  40. this.playlist = [];
  41. /**
  42. * Event will be called when tour starts to play,
  43. * before any playlist entry starts to play.
  44. * @type Event
  45. */
  46. this.tourStart = new Event();
  47. /**
  48. * Event will be called when all playlist entries are
  49. * played, or tour playback being canceled.
  50. *
  51. * If tour playback was terminated, event callback will
  52. * be called with terminated=true parameter.
  53. * @type Event
  54. */
  55. this.tourEnd = new Event();
  56. /**
  57. * Event will be called when entry from playlist starts to play.
  58. *
  59. * Event callback will be called with curent entry as first parameter.
  60. * @type Event
  61. */
  62. this.entryStart = new Event();
  63. /**
  64. * Event will be called when entry from playlist ends to play.
  65. *
  66. * Event callback will be called with following parameters:
  67. * 1. entry - entry
  68. * 2. terminated - true if playback was terminated by calling {@link KmlTour#stop}
  69. * @type Event
  70. */
  71. this.entryEnd = new Event();
  72. this._activeEntries = [];
  73. }
  74. /**
  75. * Add entry to this tour playlist.
  76. *
  77. * @param {KmlTourFlyTo|KmlTourWait} entry an entry to add to the playlist.
  78. */
  79. KmlTour.prototype.addPlaylistEntry = function (entry) {
  80. this.playlist.push(entry);
  81. };
  82. /**
  83. * Play this tour.
  84. *
  85. * @param {Viewer|CesiumWidget} widget The widget.
  86. * @param {object} [cameraOptions] these options will be merged with {@link Camera#flyTo}
  87. * options for FlyTo playlist entries.
  88. */
  89. KmlTour.prototype.play = function (widget, cameraOptions) {
  90. // We want to avoid importing the Viewer/CesiumWidget class, so we check
  91. // for the presence of the .cesiumWidget property that's only available
  92. // on the Viewer.
  93. if (defined(widget.cesiumWidget)) {
  94. deprecationWarning(
  95. "viewer",
  96. "The viewer parameter has been deprecated in Cesium 1.99. It will be removed in 1.100. Instead of a Viewer, pass a CesiumWidget instead."
  97. );
  98. }
  99. this.tourStart.raiseEvent();
  100. const tour = this;
  101. playEntry.call(this, widget, cameraOptions, function (terminated) {
  102. tour.playlistIndex = 0;
  103. // Stop nonblocking entries
  104. if (!terminated) {
  105. cancelAllEntries(tour._activeEntries);
  106. }
  107. tour.tourEnd.raiseEvent(terminated);
  108. });
  109. };
  110. /**
  111. * Stop curently playing tour.
  112. */
  113. KmlTour.prototype.stop = function () {
  114. cancelAllEntries(this._activeEntries);
  115. };
  116. // Stop all activeEntries.
  117. function cancelAllEntries(activeEntries) {
  118. for (
  119. let entry = activeEntries.pop();
  120. entry !== undefined;
  121. entry = activeEntries.pop()
  122. ) {
  123. entry.stop();
  124. }
  125. }
  126. // Play playlist entry.
  127. // This function is called recursevly with playNext and iterates over all entries from playlist.
  128. function playEntry(widget, cameraOptions, allDone) {
  129. const entry = this.playlist[this.playlistIndex];
  130. if (entry) {
  131. const _playNext = playNext.bind(this, widget, cameraOptions, allDone);
  132. this._activeEntries.push(entry);
  133. this.entryStart.raiseEvent(entry);
  134. if (entry.blocking) {
  135. entry.play(_playNext, widget.scene.camera, cameraOptions);
  136. } else {
  137. const tour = this;
  138. entry.play(function () {
  139. tour.entryEnd.raiseEvent(entry);
  140. const indx = tour._activeEntries.indexOf(entry);
  141. if (indx >= 0) {
  142. tour._activeEntries.splice(indx, 1);
  143. }
  144. });
  145. _playNext(widget, cameraOptions, allDone);
  146. }
  147. } else if (defined(allDone)) {
  148. allDone(false);
  149. }
  150. }
  151. // Increment playlistIndex and call playEntry if terminated isn't true.
  152. function playNext(widget, cameraOptions, allDone, terminated) {
  153. const entry = this.playlist[this.playlistIndex];
  154. this.entryEnd.raiseEvent(entry, terminated);
  155. if (terminated) {
  156. allDone(terminated);
  157. } else {
  158. const indx = this._activeEntries.indexOf(entry);
  159. if (indx >= 0) {
  160. this._activeEntries.splice(indx, 1);
  161. }
  162. this.playlistIndex++;
  163. playEntry.call(this, widget, cameraOptions, allDone);
  164. }
  165. }
  166. export default KmlTour;