loadingScreen.ts 11 KB

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