Default index.html

This is the default index.html that bevy build web and bevy run web uses to load your application. You may customize index.html by creating a web/index.html to override the default. The default is provided below, so you can copy it instead of writing your own from scratch:

Warning

The default index.html has the following line:

import init from "./build/bevy_app.js";

You will need to replace bevy_app with the name of your compiled binary. This is usually your crate's name, but it can be customized in Cargo.toml with the [[bin]] table, so be careful!

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8" />
    <style>
      /* Styles for the loading screen */
      :root {
        --web-bg-color: #2b2c2f;
        --web-color: white;
      }

      * {
        margin: 0;
        padding: 0;
        border: 0;
      }

      html,
      body {
        width: 100%;
        height: 100%;
      }

      .center {
        width: 100%;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        flex-direction: column;
      }

      body {
        background-color: var(--web-bg-color);
        color: var(--web-color);
      }

      .spinner {
        width: 128px;
        height: 128px;
        border: 64px solid transparent;
        border-bottom-color: #ececec;
        border-right-color: #b2b2b2;
        border-top-color: #787878;
        border-radius: 50%;
        box-sizing: border-box;
        animation: spin 1.2s linear infinite;
      }

      @keyframes spin {
        0% {
          transform: rotate(0deg);
        }

        100% {
          transform: rotate(360deg);
        }
      }
    </style>
  </head>

  <body class="center">
    <noscript>JavaScript support is required to run this app</noscript>
    <div id="loading-screen" class="center">
      <span class="spinner"></span>
    </div>

    <script type="module">
      // Automatically restart the audio context after user interaction
      // Needs to be executed _before_ the game is loaded
      // Taken from https://developer.chrome.com/blog/web-audio-autoplay/#moving-forward
      (function () {
        // An array of all contexts to resume on the page
        const audioContextList = [];

        // An array of various user interaction events we should listen for
        const userInputEventNames = [
          "click",
          "contextmenu",
          "auxclick",
          "dblclick",
          "mousedown",
          "mouseup",
          "pointerup",
          "touchend",
          "keydown",
          "keyup",
        ];

        // A proxy object to intercept AudioContexts and
        // add them to the array for tracking and resuming later
        self.AudioContext = new Proxy(self.AudioContext, {
          construct(target, args) {
            const result = new target(...args);
            audioContextList.push(result);
            return result;
          },
        });

        // To resume all AudioContexts being tracked
        function resumeAllContexts(event) {
          let count = 0;

          audioContextList.forEach((context) => {
            if (context.state !== "running") {
              context.resume();
            } else {
              count++;
            }
          });

          // If all the AudioContexts have now resumed then we
          // unbind all the event listeners from the page to prevent
          // unnecessary resume attempts
          if (count == audioContextList.length) {
            userInputEventNames.forEach((eventName) => {
              document.removeEventListener(eventName, resumeAllContexts);
            });
          }
        }

        // We bind the resume function for each user interaction
        // event on the page
        userInputEventNames.forEach((eventName) => {
          document.addEventListener(eventName, resumeAllContexts);
        });
      })();
    </script>

    <script type="module">
      // Starting the game

      // When this file is used as the default `index.html`, the CLI will automatically replace
      // `bevy_app.js` with the name of the generated JS entrypoint. If you copy this file and
      // customize it, you will need to manually change the name. For more information, please see
      // <https://thebevyflock.github.io/bevy_cli/cli/web/default-index-html.html>!
      import init from "./build/bevy_app.js";
      init().catch((error) => {
        if (
          !error.message.startsWith(
            "Using exceptions for control flow, don't mind me. This isn't actually an error!"
          )
        ) {
          throw error;
        }
      });
    </script>

    <script type="module">
      // Hide loading screen when the game starts.
      const loading_screen = document.getElementById("loading-screen");
      const observer = new MutationObserver((records) => {
        for (const record of records) {
          for (const addedNode of record.addedNodes) {
            if (addedNode instanceof HTMLCanvasElement) {
              if (addedNode.innerText.trim().length === 0) {
                // Add compatibility note
                addedNode.innerText =
                  "Canvas support is required to run this app";
              }

              // A new canvas has been created, which means that the game has been loaded
              // Hide the loading screen!
              loading_screen.style.display = "none";
              observer.disconnect();
              return;
            }
          }
        }
      });

      observer.observe(document.body, {
        subtree: false,
        childList: true,
        attributes: false,
        characterData: false,
      });
    </script>
  </body>
</html>