SelectionIndicatorViewModel.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import Cartesian2 from '../../Core/Cartesian2.js';
  2. import defaultValue from '../../Core/defaultValue.js';
  3. import defined from '../../Core/defined.js';
  4. import defineProperties from '../../Core/defineProperties.js';
  5. import DeveloperError from '../../Core/DeveloperError.js';
  6. import EasingFunction from '../../Core/EasingFunction.js';
  7. import SceneTransforms from '../../Scene/SceneTransforms.js';
  8. import knockout from '../../ThirdParty/knockout.js';
  9. var screenSpacePos = new Cartesian2();
  10. var offScreen = '-1000px';
  11. /**
  12. * The view model for {@link SelectionIndicator}.
  13. * @alias SelectionIndicatorViewModel
  14. * @constructor
  15. *
  16. * @param {Scene} scene The scene instance to use for screen-space coordinate conversion.
  17. * @param {Element} selectionIndicatorElement The element containing all elements that make up the selection indicator.
  18. * @param {Element} container The DOM element that contains the widget.
  19. */
  20. function SelectionIndicatorViewModel(scene, selectionIndicatorElement, container) {
  21. //>>includeStart('debug', pragmas.debug);
  22. if (!defined(scene)) {
  23. throw new DeveloperError('scene is required.');
  24. }
  25. if (!defined(selectionIndicatorElement)) {
  26. throw new DeveloperError('selectionIndicatorElement is required.');
  27. }
  28. if (!defined(container)) {
  29. throw new DeveloperError('container is required.');
  30. }
  31. //>>includeEnd('debug')
  32. this._scene = scene;
  33. this._screenPositionX = offScreen;
  34. this._screenPositionY = offScreen;
  35. this._tweens = scene.tweens;
  36. this._container = defaultValue(container, document.body);
  37. this._selectionIndicatorElement = selectionIndicatorElement;
  38. this._scale = 1;
  39. /**
  40. * Gets or sets the world position of the object for which to display the selection indicator.
  41. * @type {Cartesian3}
  42. */
  43. this.position = undefined;
  44. /**
  45. * Gets or sets the visibility of the selection indicator.
  46. * @type {Boolean}
  47. */
  48. this.showSelection = false;
  49. knockout.track(this, ['position', '_screenPositionX', '_screenPositionY', '_scale', 'showSelection']);
  50. /**
  51. * Gets the visibility of the position indicator. This can be false even if an
  52. * object is selected, when the selected object has no position.
  53. * @type {Boolean}
  54. */
  55. this.isVisible = undefined;
  56. knockout.defineProperty(this, 'isVisible', {
  57. get : function() {
  58. return this.showSelection && defined(this.position);
  59. }
  60. });
  61. knockout.defineProperty(this, '_transform', {
  62. get : function() {
  63. return 'scale(' + (this._scale) + ')';
  64. }
  65. });
  66. /**
  67. * Gets or sets the function for converting the world position of the object to the screen space position.
  68. *
  69. * @member
  70. * @type {SelectionIndicatorViewModel~ComputeScreenSpacePosition}
  71. * @default SceneTransforms.wgs84ToWindowCoordinates
  72. *
  73. * @example
  74. * selectionIndicatorViewModel.computeScreenSpacePosition = function(position, result) {
  75. * return Cesium.SceneTransforms.wgs84ToWindowCoordinates(scene, position, result);
  76. * };
  77. */
  78. this.computeScreenSpacePosition = function(position, result) {
  79. return SceneTransforms.wgs84ToWindowCoordinates(scene, position, result);
  80. };
  81. }
  82. /**
  83. * Updates the view of the selection indicator to match the position and content properties of the view model.
  84. * This function should be called as part of the render loop.
  85. */
  86. SelectionIndicatorViewModel.prototype.update = function() {
  87. if (this.showSelection && defined(this.position)) {
  88. var screenPosition = this.computeScreenSpacePosition(this.position, screenSpacePos);
  89. if (!defined(screenPosition)) {
  90. this._screenPositionX = offScreen;
  91. this._screenPositionY = offScreen;
  92. } else {
  93. var container = this._container;
  94. var containerWidth = container.parentNode.clientWidth;
  95. var containerHeight = container.parentNode.clientHeight;
  96. var indicatorSize = this._selectionIndicatorElement.clientWidth;
  97. var halfSize = indicatorSize * 0.5;
  98. screenPosition.x = Math.min(Math.max(screenPosition.x, -indicatorSize), containerWidth + indicatorSize) - halfSize;
  99. screenPosition.y = Math.min(Math.max(screenPosition.y, -indicatorSize), containerHeight + indicatorSize) - halfSize;
  100. this._screenPositionX = Math.floor(screenPosition.x + 0.25) + 'px';
  101. this._screenPositionY = Math.floor(screenPosition.y + 0.25) + 'px';
  102. }
  103. }
  104. };
  105. /**
  106. * Animate the indicator to draw attention to the selection.
  107. */
  108. SelectionIndicatorViewModel.prototype.animateAppear = function() {
  109. this._tweens.addProperty({
  110. object : this,
  111. property : '_scale',
  112. startValue : 2,
  113. stopValue : 1,
  114. duration : 0.8,
  115. easingFunction : EasingFunction.EXPONENTIAL_OUT
  116. });
  117. };
  118. /**
  119. * Animate the indicator to release the selection.
  120. */
  121. SelectionIndicatorViewModel.prototype.animateDepart = function() {
  122. this._tweens.addProperty({
  123. object : this,
  124. property : '_scale',
  125. startValue : this._scale,
  126. stopValue : 1.5,
  127. duration : 0.8,
  128. easingFunction : EasingFunction.EXPONENTIAL_OUT
  129. });
  130. };
  131. defineProperties(SelectionIndicatorViewModel.prototype, {
  132. /**
  133. * Gets the HTML element containing the selection indicator.
  134. * @memberof SelectionIndicatorViewModel.prototype
  135. *
  136. * @type {Element}
  137. */
  138. container : {
  139. get : function() {
  140. return this._container;
  141. }
  142. },
  143. /**
  144. * Gets the HTML element that holds the selection indicator.
  145. * @memberof SelectionIndicatorViewModel.prototype
  146. *
  147. * @type {Element}
  148. */
  149. selectionIndicatorElement : {
  150. get : function() {
  151. return this._selectionIndicatorElement;
  152. }
  153. },
  154. /**
  155. * Gets the scene being used.
  156. * @memberof SelectionIndicatorViewModel.prototype
  157. *
  158. * @type {Scene}
  159. */
  160. scene : {
  161. get : function() {
  162. return this._scene;
  163. }
  164. }
  165. });
  166. /**
  167. * A function that converts the world position of an object to a screen space position.
  168. * @callback SelectionIndicatorViewModel~ComputeScreenSpacePosition
  169. * @param {Cartesian3} position The position in WGS84 (world) coordinates.
  170. * @param {Cartesian2} result An object to return the input position transformed to window coordinates.
  171. * @returns {Cartesian2} The modified result parameter.
  172. */
  173. export default SelectionIndicatorViewModel;