KmlTour.js 4.3 KB

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