loadingScreen.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. import { AbstractEngine } from "../Engines/abstractEngine.js";
  2. /**
  3. * Class used for the default loading screen
  4. * @see https://doc.babylonjs.com/features/featuresDeepDive/scene/customLoadingScreen
  5. */
  6. export class DefaultLoadingScreen {
  7. /**
  8. * Creates a new default loading screen
  9. * @param _renderingCanvas defines the canvas used to render the scene
  10. * @param _loadingText defines the default text to display
  11. * @param _loadingDivBackgroundColor defines the default background color
  12. */
  13. constructor(_renderingCanvas, _loadingText = "", _loadingDivBackgroundColor = "black") {
  14. this._renderingCanvas = _renderingCanvas;
  15. this._loadingText = _loadingText;
  16. this._loadingDivBackgroundColor = _loadingDivBackgroundColor;
  17. // Resize
  18. this._resizeLoadingUI = () => {
  19. const canvasRect = this._renderingCanvas.getBoundingClientRect();
  20. const canvasPositioning = window.getComputedStyle(this._renderingCanvas).position;
  21. if (!this._loadingDiv) {
  22. return;
  23. }
  24. this._loadingDiv.style.position = canvasPositioning === "fixed" ? "fixed" : "absolute";
  25. this._loadingDiv.style.left = canvasRect.left + "px";
  26. this._loadingDiv.style.top = canvasRect.top + "px";
  27. this._loadingDiv.style.width = canvasRect.width + "px";
  28. this._loadingDiv.style.height = canvasRect.height + "px";
  29. };
  30. }
  31. /**
  32. * Function called to display the loading screen
  33. */
  34. displayLoadingUI() {
  35. if (this._loadingDiv) {
  36. // Do not add a loading screen if there is already one
  37. return;
  38. }
  39. this._loadingDiv = document.createElement("div");
  40. this._loadingDiv.id = "babylonjsLoadingDiv";
  41. this._loadingDiv.style.opacity = "0";
  42. this._loadingDiv.style.transition = "opacity 1.5s ease";
  43. this._loadingDiv.style.pointerEvents = "none";
  44. this._loadingDiv.style.display = "grid";
  45. this._loadingDiv.style.gridTemplateRows = "100%";
  46. this._loadingDiv.style.gridTemplateColumns = "100%";
  47. this._loadingDiv.style.justifyItems = "center";
  48. this._loadingDiv.style.alignItems = "center";
  49. // Loading text
  50. this._loadingTextDiv = document.createElement("div");
  51. this._loadingTextDiv.style.position = "absolute";
  52. this._loadingTextDiv.style.left = "0";
  53. this._loadingTextDiv.style.top = "50%";
  54. this._loadingTextDiv.style.marginTop = "80px";
  55. this._loadingTextDiv.style.width = "100%";
  56. this._loadingTextDiv.style.height = "20px";
  57. this._loadingTextDiv.style.fontFamily = "Arial";
  58. this._loadingTextDiv.style.fontSize = "14px";
  59. this._loadingTextDiv.style.color = "white";
  60. this._loadingTextDiv.style.textAlign = "center";
  61. this._loadingTextDiv.style.zIndex = "1";
  62. this._loadingTextDiv.innerHTML = "Loading";
  63. this._loadingDiv.appendChild(this._loadingTextDiv);
  64. //set the predefined text
  65. this._loadingTextDiv.innerHTML = this._loadingText;
  66. // Generating keyframes
  67. this._style = document.createElement("style");
  68. this._style.type = "text/css";
  69. const keyFrames = `@-webkit-keyframes spin1 {\
  70. 0% { -webkit-transform: rotate(0deg);}
  71. 100% { -webkit-transform: rotate(360deg);}
  72. }\
  73. @keyframes spin1 {\
  74. 0% { transform: rotate(0deg);}
  75. 100% { transform: rotate(360deg);}
  76. }`;
  77. this._style.innerHTML = keyFrames;
  78. document.getElementsByTagName("head")[0].appendChild(this._style);
  79. const svgSupport = !!window.SVGSVGElement;
  80. // Loading img
  81. const imgBack = new Image();
  82. if (!DefaultLoadingScreen.DefaultLogoUrl) {
  83. imgBack.src = !svgSupport
  84. ? "https://cdn.babylonjs.com/Assets/babylonLogo.png"
  85. : `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAxODAuMTcgMjA4LjA0Ij48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2ZmZjt9LmNscy0ye2ZpbGw6I2UwNjg0Yjt9LmNscy0ze2ZpbGw6I2JiNDY0Yjt9LmNscy00e2ZpbGw6I2UwZGVkODt9LmNscy01e2ZpbGw6I2Q1ZDJjYTt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPkJhYnlsb25Mb2dvPC90aXRsZT48ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIj48ZyBpZD0iUGFnZV9FbGVtZW50cyIgZGF0YS1uYW1lPSJQYWdlIEVsZW1lbnRzIj48cGF0aCBjbGFzcz0iY2xzLTEiIGQ9Ik05MC4wOSwwLDAsNTJWMTU2bDkwLjA5LDUyLDkwLjA4LTUyVjUyWiIvPjxwb2x5Z29uIGNsYXNzPSJjbHMtMiIgcG9pbnRzPSIxODAuMTcgNTIuMDEgMTUxLjk3IDM1LjczIDEyNC44NSA1MS4zOSAxNTMuMDUgNjcuNjcgMTgwLjE3IDUyLjAxIi8+PHBvbHlnb24gY2xhc3M9ImNscy0yIiBwb2ludHM9IjI3LjEyIDY3LjY3IDExNy4yMSAxNS42NiA5MC4wOCAwIDAgNTIuMDEgMjcuMTIgNjcuNjciLz48cG9seWdvbiBjbGFzcz0iY2xzLTIiIHBvaW50cz0iNjEuODkgMTIwLjMgOTAuMDggMTM2LjU4IDExOC4yOCAxMjAuMyA5MC4wOCAxMDQuMDIgNjEuODkgMTIwLjMiLz48cG9seWdvbiBjbGFzcz0iY2xzLTMiIHBvaW50cz0iMTUzLjA1IDY3LjY3IDE1My4wNSAxNDAuMzcgOTAuMDggMTc2LjcyIDI3LjEyIDE0MC4zNyAyNy4xMiA2Ny42NyAwIDUyLjAxIDAgMTU2LjAzIDkwLjA4IDIwOC4wNCAxODAuMTcgMTU2LjAzIDE4MC4xNyA1Mi4wMSAxNTMuMDUgNjcuNjciLz48cG9seWdvbiBjbGFzcz0iY2xzLTMiIHBvaW50cz0iOTAuMDggNzEuNDYgNjEuODkgODcuNzQgNjEuODkgMTIwLjMgOTAuMDggMTA0LjAyIDExOC4yOCAxMjAuMyAxMTguMjggODcuNzQgOTAuMDggNzEuNDYiLz48cG9seWdvbiBjbGFzcz0iY2xzLTQiIHBvaW50cz0iMTUzLjA1IDY3LjY3IDExOC4yOCA4Ny43NCAxMTguMjggMTIwLjMgOTAuMDggMTM2LjU4IDkwLjA4IDE3Ni43MiAxNTMuMDUgMTQwLjM3IDE1My4wNSA2Ny42NyIvPjxwb2x5Z29uIGNsYXNzPSJjbHMtNSIgcG9pbnRzPSIyNy4xMiA2Ny42NyA2MS44OSA4Ny43NCA2MS44OSAxMjAuMyA5MC4wOCAxMzYuNTggOTAuMDggMTc2LjcyIDI3LjEyIDE0MC4zNyAyNy4xMiA2Ny42NyIvPjwvZz48L2c+PC9zdmc+`;
  86. }
  87. else {
  88. imgBack.src = DefaultLoadingScreen.DefaultLogoUrl;
  89. }
  90. imgBack.style.width = "150px";
  91. imgBack.style.gridColumn = "1";
  92. imgBack.style.gridRow = "1";
  93. imgBack.style.top = "50%";
  94. imgBack.style.left = "50%";
  95. imgBack.style.transform = "translate(-50%, -50%)";
  96. imgBack.style.position = "absolute";
  97. const imageSpinnerContainer = document.createElement("div");
  98. imageSpinnerContainer.style.width = "300px";
  99. imageSpinnerContainer.style.gridColumn = "1";
  100. imageSpinnerContainer.style.gridRow = "1";
  101. imageSpinnerContainer.style.top = "50%";
  102. imageSpinnerContainer.style.left = "50%";
  103. imageSpinnerContainer.style.transform = "translate(-50%, -50%)";
  104. imageSpinnerContainer.style.position = "absolute";
  105. // Loading spinner
  106. const imgSpinner = new Image();
  107. if (!DefaultLoadingScreen.DefaultSpinnerUrl) {
  108. imgSpinner.src = !svgSupport
  109. ? "https://cdn.babylonjs.com/Assets/loadingIcon.png"
  110. : `data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAzOTIgMzkyIj48ZGVmcz48c3R5bGU+LmNscy0xe2ZpbGw6I2UwNjg0Yjt9LmNscy0ye2ZpbGw6bm9uZTt9PC9zdHlsZT48L2RlZnM+PHRpdGxlPlNwaW5uZXJJY29uPC90aXRsZT48ZyBpZD0iTGF5ZXJfMiIgZGF0YS1uYW1lPSJMYXllciAyIj48ZyBpZD0iU3Bpbm5lciI+PHBhdGggY2xhc3M9ImNscy0xIiBkPSJNNDAuMjEsMTI2LjQzYzMuNy03LjMxLDcuNjctMTQuNDQsMTItMjEuMzJsMy4zNi01LjEsMy41Mi01YzEuMjMtMS42MywyLjQxLTMuMjksMy42NS00LjkxczIuNTMtMy4yMSwzLjgyLTQuNzlBMTg1LjIsMTg1LjIsMCwwLDEsODMuNCw2Ny40M2EyMDgsMjA4LDAsMCwxLDE5LTE1LjY2YzMuMzUtMi40MSw2Ljc0LTQuNzgsMTAuMjUtN3M3LjExLTQuMjgsMTAuNzUtNi4zMmM3LjI5LTQsMTQuNzMtOCwyMi41My0xMS40OSwzLjktMS43Miw3Ljg4LTMuMywxMi00LjY0YTEwNC4yMiwxMDQuMjIsMCwwLDEsMTIuNDQtMy4yMyw2Mi40NCw2Mi40NCwwLDAsMSwxMi43OC0xLjM5QTI1LjkyLDI1LjkyLDAsMCwxLDE5NiwyMS40NGE2LjU1LDYuNTUsMCwwLDEsMi4wNSw5LDYuNjYsNi42NiwwLDAsMS0xLjY0LDEuNzhsLS40MS4yOWEyMi4wNywyMi4wNywwLDAsMS01Ljc4LDMsMzAuNDIsMzAuNDIsMCwwLDEtNS42NywxLjYyLDM3LjgyLDM3LjgyLDAsMCwxLTUuNjkuNzFjLTEsMC0xLjkuMTgtMi44NS4yNmwtMi44NS4yNHEtNS43Mi41MS0xMS40OCwxLjFjLTMuODQuNC03LjcxLjgyLTExLjU4LDEuNGExMTIuMzQsMTEyLjM0LDAsMCwwLTIyLjk0LDUuNjFjLTMuNzIsMS4zNS03LjM0LDMtMTAuOTQsNC42NHMtNy4xNCwzLjUxLTEwLjYsNS41MUExNTEuNiwxNTEuNiwwLDAsMCw2OC41Niw4N0M2Ny4yMyw4OC40OCw2Niw5MCw2NC42NCw5MS41NnMtMi41MSwzLjE1LTMuNzUsNC43M2wtMy41NCw0LjljLTEuMTMsMS42Ni0yLjIzLDMuMzUtMy4zMyw1YTEyNywxMjcsMCwwLDAtMTAuOTMsMjEuNDksMS41OCwxLjU4LDAsMSwxLTMtMS4xNVM0MC4xOSwxMjYuNDcsNDAuMjEsMTI2LjQzWiIvPjxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjM5MiIgaGVpZ2h0PSIzOTIiLz48L2c+PC9nPjwvc3ZnPg==`;
  111. }
  112. else {
  113. imgSpinner.src = DefaultLoadingScreen.DefaultSpinnerUrl;
  114. }
  115. imgSpinner.style.animation = "spin1 0.75s infinite linear";
  116. imgSpinner.style.webkitAnimation = "spin1 0.75s infinite linear";
  117. imgSpinner.style.transformOrigin = "50% 50%";
  118. imgSpinner.style.webkitTransformOrigin = "50% 50%";
  119. if (!svgSupport) {
  120. const logoSize = { w: 16, h: 18.5 };
  121. const loadingSize = { w: 30, h: 30 };
  122. // set styling correctly
  123. imgBack.style.width = `${logoSize.w}vh`;
  124. imgBack.style.height = `${logoSize.h}vh`;
  125. imgBack.style.left = `calc(50% - ${logoSize.w / 2}vh)`;
  126. imgBack.style.top = `calc(50% - ${logoSize.h / 2}vh)`;
  127. imgSpinner.style.width = `${loadingSize.w}vh`;
  128. imgSpinner.style.height = `${loadingSize.h}vh`;
  129. imgSpinner.style.left = `calc(50% - ${loadingSize.w / 2}vh)`;
  130. imgSpinner.style.top = `calc(50% - ${loadingSize.h / 2}vh)`;
  131. }
  132. imageSpinnerContainer.appendChild(imgSpinner);
  133. this._loadingDiv.appendChild(imgBack);
  134. this._loadingDiv.appendChild(imageSpinnerContainer);
  135. this._resizeLoadingUI();
  136. window.addEventListener("resize", this._resizeLoadingUI);
  137. this._loadingDiv.style.backgroundColor = this._loadingDivBackgroundColor;
  138. document.body.appendChild(this._loadingDiv);
  139. this._loadingDiv.style.opacity = "1";
  140. }
  141. /**
  142. * Function called to hide the loading screen
  143. */
  144. hideLoadingUI() {
  145. if (!this._loadingDiv) {
  146. return;
  147. }
  148. const onTransitionEnd = () => {
  149. if (this._loadingTextDiv) {
  150. this._loadingTextDiv.remove();
  151. this._loadingTextDiv = null;
  152. }
  153. if (this._loadingDiv) {
  154. this._loadingDiv.remove();
  155. this._loadingDiv = null;
  156. }
  157. if (this._style) {
  158. this._style.remove();
  159. this._style = null;
  160. }
  161. window.removeEventListener("resize", this._resizeLoadingUI);
  162. };
  163. this._loadingDiv.style.opacity = "0";
  164. this._loadingDiv.addEventListener("transitionend", onTransitionEnd);
  165. }
  166. /**
  167. * Gets or sets the text to display while loading
  168. */
  169. set loadingUIText(text) {
  170. this._loadingText = text;
  171. if (this._loadingTextDiv) {
  172. this._loadingTextDiv.innerHTML = this._loadingText;
  173. }
  174. }
  175. get loadingUIText() {
  176. return this._loadingText;
  177. }
  178. /**
  179. * Gets or sets the color to use for the background
  180. */
  181. get loadingUIBackgroundColor() {
  182. return this._loadingDivBackgroundColor;
  183. }
  184. set loadingUIBackgroundColor(color) {
  185. this._loadingDivBackgroundColor = color;
  186. if (!this._loadingDiv) {
  187. return;
  188. }
  189. this._loadingDiv.style.backgroundColor = this._loadingDivBackgroundColor;
  190. }
  191. }
  192. /** Gets or sets the logo url to use for the default loading screen */
  193. DefaultLoadingScreen.DefaultLogoUrl = "";
  194. /** Gets or sets the spinner url to use for the default loading screen */
  195. DefaultLoadingScreen.DefaultSpinnerUrl = "";
  196. AbstractEngine.DefaultLoadingScreenFactory = (canvas) => {
  197. return new DefaultLoadingScreen(canvas);
  198. };
  199. //# sourceMappingURL=loadingScreen.js.map