NavigationHelpButton.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. import {
  2. buildModuleUrl,
  3. defaultValue,
  4. defined,
  5. destroyObject,
  6. DeveloperError,
  7. FeatureDetection,
  8. getElement,
  9. } from "@cesium/engine";
  10. import knockout from "../ThirdParty/knockout.js";
  11. import NavigationHelpButtonViewModel from "./NavigationHelpButtonViewModel.js";
  12. /**
  13. * <p>The NavigationHelpButton is a single button widget for displaying instructions for
  14. * navigating the globe with the mouse.</p><p style="clear: both;"></p><br/>
  15. *
  16. * @alias NavigationHelpButton
  17. * @constructor
  18. *
  19. * @param {object} options Object with the following properties:
  20. * @param {Element|string} options.container The DOM element or ID that will contain the widget.
  21. * @param {boolean} [options.instructionsInitiallyVisible=false] True if the navigation instructions should initially be visible; otherwise, false.
  22. *
  23. * @exception {DeveloperError} Element with id "container" does not exist in the document.
  24. *
  25. * @example
  26. * // In HTML head, include a link to the NavigationHelpButton.css stylesheet,
  27. * // and in the body, include: <div id="navigationHelpButtonContainer"></div>
  28. *
  29. * const navigationHelpButton = new Cesium.NavigationHelpButton({
  30. * container : 'navigationHelpButtonContainer'
  31. * });
  32. */
  33. function NavigationHelpButton(options) {
  34. //>>includeStart('debug', pragmas.debug);
  35. if (!defined(options) || !defined(options.container)) {
  36. throw new DeveloperError("options.container is required.");
  37. }
  38. //>>includeEnd('debug');
  39. const container = getElement(options.container);
  40. const viewModel = new NavigationHelpButtonViewModel();
  41. const showInsructionsDefault = defaultValue(
  42. options.instructionsInitiallyVisible,
  43. false
  44. );
  45. viewModel.showInstructions = showInsructionsDefault;
  46. viewModel._svgPath =
  47. "M16,1.466C7.973,1.466,1.466,7.973,1.466,16c0,8.027,6.507,14.534,14.534,14.534c8.027,0,14.534-6.507,14.534-14.534C30.534,7.973,24.027,1.466,16,1.466z M17.328,24.371h-2.707v-2.596h2.707V24.371zM17.328,19.003v0.858h-2.707v-1.057c0-3.19,3.63-3.696,3.63-5.963c0-1.034-0.924-1.826-2.134-1.826c-1.254,0-2.354,0.924-2.354,0.924l-1.541-1.915c0,0,1.519-1.584,4.137-1.584c2.487,0,4.796,1.54,4.796,4.136C21.156,16.208,17.328,16.627,17.328,19.003z";
  48. const wrapper = document.createElement("span");
  49. wrapper.className = "cesium-navigationHelpButton-wrapper";
  50. container.appendChild(wrapper);
  51. const button = document.createElement("button");
  52. button.type = "button";
  53. button.className =
  54. "cesium-button cesium-toolbar-button cesium-navigation-help-button";
  55. button.setAttribute(
  56. "data-bind",
  57. "\
  58. attr: { title: tooltip },\
  59. click: command,\
  60. cesiumSvgPath: { path: _svgPath, width: 32, height: 32 }"
  61. );
  62. wrapper.appendChild(button);
  63. const instructionContainer = document.createElement("div");
  64. instructionContainer.className = "cesium-navigation-help";
  65. instructionContainer.setAttribute(
  66. "data-bind",
  67. 'css: { "cesium-navigation-help-visible" : showInstructions}'
  68. );
  69. wrapper.appendChild(instructionContainer);
  70. const mouseButton = document.createElement("button");
  71. mouseButton.type = "button";
  72. mouseButton.className =
  73. "cesium-navigation-button cesium-navigation-button-left";
  74. mouseButton.setAttribute(
  75. "data-bind",
  76. 'click: showClick, css: {"cesium-navigation-button-selected": !_touch, "cesium-navigation-button-unselected": _touch}'
  77. );
  78. const mouseIcon = document.createElement("img");
  79. mouseIcon.src = buildModuleUrl("Widgets/Images/NavigationHelp/Mouse.svg");
  80. mouseIcon.className = "cesium-navigation-button-icon";
  81. mouseIcon.style.width = "25px";
  82. mouseIcon.style.height = "25px";
  83. mouseButton.appendChild(mouseIcon);
  84. mouseButton.appendChild(document.createTextNode("Mouse"));
  85. const touchButton = document.createElement("button");
  86. touchButton.type = "button";
  87. touchButton.className =
  88. "cesium-navigation-button cesium-navigation-button-right";
  89. touchButton.setAttribute(
  90. "data-bind",
  91. 'click: showTouch, css: {"cesium-navigation-button-selected": _touch, "cesium-navigation-button-unselected": !_touch}'
  92. );
  93. const touchIcon = document.createElement("img");
  94. touchIcon.src = buildModuleUrl("Widgets/Images/NavigationHelp/Touch.svg");
  95. touchIcon.className = "cesium-navigation-button-icon";
  96. touchIcon.style.width = "25px";
  97. touchIcon.style.height = "25px";
  98. touchButton.appendChild(touchIcon);
  99. touchButton.appendChild(document.createTextNode("Touch"));
  100. instructionContainer.appendChild(mouseButton);
  101. instructionContainer.appendChild(touchButton);
  102. const clickInstructions = document.createElement("div");
  103. clickInstructions.className =
  104. "cesium-click-navigation-help cesium-navigation-help-instructions";
  105. clickInstructions.setAttribute(
  106. "data-bind",
  107. 'css: { "cesium-click-navigation-help-visible" : !_touch}'
  108. );
  109. clickInstructions.innerHTML = `\
  110. <table>\
  111. <tr>\
  112. <td><img src="${buildModuleUrl(
  113. "Widgets/Images/NavigationHelp/MouseLeft.svg"
  114. )}" width="48" height="48" /></td>\
  115. <td>\
  116. <div class="cesium-navigation-help-pan">Pan view</div>\
  117. <div class="cesium-navigation-help-details">Left click + drag</div>\
  118. </td>\
  119. </tr>\
  120. <tr>\
  121. <td><img src="${buildModuleUrl(
  122. "Widgets/Images/NavigationHelp/MouseRight.svg"
  123. )}" width="48" height="48" /></td>\
  124. <td>\
  125. <div class="cesium-navigation-help-zoom">Zoom view</div>\
  126. <div class="cesium-navigation-help-details">Right click + drag, or</div>\
  127. <div class="cesium-navigation-help-details">Mouse wheel scroll</div>\
  128. </td>\
  129. </tr>\
  130. <tr>\
  131. <td><img src="${buildModuleUrl(
  132. "Widgets/Images/NavigationHelp/MouseMiddle.svg"
  133. )}" width="48" height="48" /></td>\
  134. <td>\
  135. <div class="cesium-navigation-help-rotate">Rotate view</div>\
  136. <div class="cesium-navigation-help-details">Middle click + drag, or</div>\
  137. <div class="cesium-navigation-help-details">CTRL + Left/Right click + drag</div>\
  138. </td>\
  139. </tr>\
  140. </table>`;
  141. instructionContainer.appendChild(clickInstructions);
  142. const touchInstructions = document.createElement("div");
  143. touchInstructions.className =
  144. "cesium-touch-navigation-help cesium-navigation-help-instructions";
  145. touchInstructions.setAttribute(
  146. "data-bind",
  147. 'css: { "cesium-touch-navigation-help-visible" : _touch}'
  148. );
  149. touchInstructions.innerHTML = `\
  150. <table>\
  151. <tr>\
  152. <td><img src="${buildModuleUrl(
  153. "Widgets/Images/NavigationHelp/TouchDrag.svg"
  154. )}" width="70" height="48" /></td>\
  155. <td>\
  156. <div class="cesium-navigation-help-pan">Pan view</div>\
  157. <div class="cesium-navigation-help-details">One finger drag</div>\
  158. </td>\
  159. </tr>\
  160. <tr>\
  161. <td><img src="${buildModuleUrl(
  162. "Widgets/Images/NavigationHelp/TouchZoom.svg"
  163. )}" width="70" height="48" /></td>\
  164. <td>\
  165. <div class="cesium-navigation-help-zoom">Zoom view</div>\
  166. <div class="cesium-navigation-help-details">Two finger pinch</div>\
  167. </td>\
  168. </tr>\
  169. <tr>\
  170. <td><img src="${buildModuleUrl(
  171. "Widgets/Images/NavigationHelp/TouchTilt.svg"
  172. )}" width="70" height="48" /></td>\
  173. <td>\
  174. <div class="cesium-navigation-help-rotate">Tilt view</div>\
  175. <div class="cesium-navigation-help-details">Two finger drag, same direction</div>\
  176. </td>\
  177. </tr>\
  178. <tr>\
  179. <td><img src="${buildModuleUrl(
  180. "Widgets/Images/NavigationHelp/TouchRotate.svg"
  181. )}" width="70" height="48" /></td>\
  182. <td>\
  183. <div class="cesium-navigation-help-tilt">Rotate view</div>\
  184. <div class="cesium-navigation-help-details">Two finger drag, opposite direction</div>\
  185. </td>\
  186. </tr>\
  187. </table>`;
  188. instructionContainer.appendChild(touchInstructions);
  189. knockout.applyBindings(viewModel, wrapper);
  190. this._container = container;
  191. this._viewModel = viewModel;
  192. this._wrapper = wrapper;
  193. this._closeInstructions = function (e) {
  194. if (!wrapper.contains(e.target)) {
  195. viewModel.showInstructions = false;
  196. }
  197. };
  198. if (FeatureDetection.supportsPointerEvents()) {
  199. document.addEventListener("pointerdown", this._closeInstructions, true);
  200. } else {
  201. document.addEventListener("mousedown", this._closeInstructions, true);
  202. document.addEventListener("touchstart", this._closeInstructions, true);
  203. }
  204. }
  205. Object.defineProperties(NavigationHelpButton.prototype, {
  206. /**
  207. * Gets the parent container.
  208. * @memberof NavigationHelpButton.prototype
  209. *
  210. * @type {Element}
  211. */
  212. container: {
  213. get: function () {
  214. return this._container;
  215. },
  216. },
  217. /**
  218. * Gets the view model.
  219. * @memberof NavigationHelpButton.prototype
  220. *
  221. * @type {NavigationHelpButtonViewModel}
  222. */
  223. viewModel: {
  224. get: function () {
  225. return this._viewModel;
  226. },
  227. },
  228. });
  229. /**
  230. * @returns {boolean} true if the object has been destroyed, false otherwise.
  231. */
  232. NavigationHelpButton.prototype.isDestroyed = function () {
  233. return false;
  234. };
  235. /**
  236. * Destroys the widget. Should be called if permanently
  237. * removing the widget from layout.
  238. */
  239. NavigationHelpButton.prototype.destroy = function () {
  240. if (FeatureDetection.supportsPointerEvents()) {
  241. document.removeEventListener("pointerdown", this._closeInstructions, true);
  242. } else {
  243. document.removeEventListener("mousedown", this._closeInstructions, true);
  244. document.removeEventListener("touchstart", this._closeInstructions, true);
  245. }
  246. knockout.cleanNode(this._wrapper);
  247. this._container.removeChild(this._wrapper);
  248. return destroyObject(this);
  249. };
  250. export default NavigationHelpButton;