Search code examples
node.jscesiumjs

Run CesiumJS with no server requirements


I downloaded Cesiumjs-1.11 and ran the official Hello World tutorial.

I want to run the same example without relying on nodejs as a server. I tried taking the ./Build/Cesium and using it with the example in the same directory.

CesiumJS runs, but I get this error:

SecurityError: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at file:://path/to/Cesium/Assets/Textures/moonSmall.jpg may not be loaded.
Error: Failed to execute 'texImage2D' on 'WebGLRenderingContext': The cross-origin image at file:://path/to/Cesium/Assets/Textures/moonSmall.jpg may not be loaded.
    at Error (native)
    at new p (file:://path/to/Cesium/Cesium.js:433:19773)
    at et.createTexture2D (file:://path/to/Cesium/Cesium.js:449:19216)
    at H.update (file:://path/to/Cesium/Cesium.js:434:9600)
    at S.update (file:://path/to/Cesium/Cesium.js:452:1298)
    at m.update (file:://path/to/Cesium/Cesium.js:455:27828)
    at vt (file:://path/to/Cesium/Cesium.js:458:15322)
    at Ct (file:://path/to/Cesium/Cesium.js:458:18817)
    at bt.render (file://path/to/Cesium/Cesium.js:458:25057)
    at P.render (file:://path/to/Cesium/Cesium.js:464:4108)

Here is the code:

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Use correct character set. -->
  <meta charset="utf-8">
  <!-- Tell IE to use the latest, best version (or Chrome Frame if pre-IE11). -->
  <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
  <!-- Make the application on mobile take up the full browser screen and disable user scaling. -->
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no">
  <title>Hello World!</title>
  <script src="Cesium/Cesium.js"></script>
  <style>
      @import url(Cesium/Widgets/widgets.css);
      html, body, #cesiumContainer {
          width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
      }
  </style>
</head>
<body>
  <div id="cesiumContainer"></div>
  <script>
    var viewer = new Cesium.Viewer('cesiumContainer');
  </script>
</body>
</html>

What's wrong with this code ?


Solution

  • There's nothing technically wrong with your code and Cesium can work offline embedded into an application without any issues. The problem here is web browser security. If you're just opening the HTML file in a browser, you are still running inside of a sandbox that restricts access to local files, especially when it comes to things like web workers and WebGL. This is preventing required files from being loaded, resulting in an error. This is true in all browsers and you can verify it yourself by temporarily disabling browser security.

    For example, in Chrome you can run with the --disable-web-security and the page will load without any errors. Note, in order for this to work you have to make sure no Chrome instance are already running. If you get a warning on startup, you know the option took. There are different options in other browsers (for example IE just prompts you to allow blocked content).

    You will still have a problem of missing imagery because the default configuration is expected to run on a server. To fix that, you can explicit define an imagery provider. Here's a complete example that works when web security is disabled.

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="utf-8">
      <meta http-equiv="X-UA-Compatible" content="IE=edge">
      <meta name="viewport" content="width=device-width, initial-scale=1,
            maximum-scale=1, minimum-scale=1, user-scalable=no">
      <title>Hello World!</title>
      <script src="../Build/Cesium/Cesium.js"></script>
      <style>
          @import url(../Build/Cesium/Widgets/widgets.css);
          html, body, #cesiumContainer {
              width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden;
          }
      </style>
    </head>
    <body>
      <div id="cesiumContainer"></div>
      <script>
        var viewer = new Cesium.Viewer('cesiumContainer', {
            baseLayerPicker: false,
            imageryProvider: new Cesium.BingMapsImageryProvider({
                        url : 'http://dev.virtualearth.net'
                    })
        });
      </script>
    </body>
    </html>
    

    I assume you're ultimate goal is trying to use Cesium embedded in an application? If so, none of these security restrictions will apply. Many people are using Cesium in embedded browser controls with success.