Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

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>