$(document).ready(function() { "use strict"; /** * The Globe encapsulates the WorldWindow object (wwd) and provides application * specific logic for interacting with layers. * @param {String} canvasId The ID of the canvas element that will host the globe * @returns {Globe} */ class Globe { constructor(canvasId) { // Create a WorldWindow globe on the specified HTML5 canvas this.wwd = new WorldWind.WorldWindow(canvasId); // Holds the next unique id to be assigned to a layer this.nextLayerId = 1; // Add a BMNGOneImageLayer background layer. We're overriding the default // minimum altitude of the BMNGOneImageLayer so this layer always available. this.addLayer(new WorldWind.BMNGOneImageLayer(), { category: "background", minActiveAltitude: 0 }); } /** * Adds a layer to the globe. Applies the optional options' properties to the * layer, and assigns the layer a unique ID and category. * @param {WorldWind.Layer} layer * @param {Object|null} options E.g., {category: "base", enabled: true} */ addLayer(layer, options) { // Copy all properties defined on the options object to the layer if (options) { for (let prop in options) { if (!options.hasOwnProperty(prop)) { continue; // skip inherited props } layer[prop] = options[prop]; } } // Assign a default category property if not already assigned if (typeof layer.category === 'undefined') { layer.category = 'overlay'; // the default category } // Assign a unique layer ID to ease layer management layer.uniqueId = this.nextLayerId++; // Add the layer to the globe this.wwd.addLayer(layer); } /** * Returns a new array of layers in the given category. * @param {String} category E.g., "base", "overlay" or "setting". * @returns {Array} */ getLayers(category) { return this.wwd.layers.filter(layer => layer.category === category); } } // Create a globe let globe = new Globe("globe-canvas"); // Add layers to the globe globe.addLayer(new WorldWind.BMNGLayer(), { category: "base" }); globe.addLayer(new WorldWind.CoordinatesDisplayLayer(globe.wwd), { category: "setting" }); globe.addLayer(new WorldWind.ViewControlsLayer(globe.wwd), { category: "setting" }); globe.addLayer(new WorldWind.CompassLayer(), { category: "setting", enabled: false }); // Auto-collapse the main menu when its button items are clicked $('.navbar-collapse a[role="button"]').click(function() { $('.navbar-collapse').collapse('hide'); }); // Collapse card ancestors when the close icon is clicked $('.collapse .close').on('click', function() { $(this).closest('.collapse').collapse('hide'); }); });
<!doctype html> <html lang="en"> <head> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <title>WorldWindJS Example</title> <!-- Bootstrap 4.0 CSS compiled and minified --> <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous"> <!-- Font Awesome icons (see: https://fontawesome.com/icons?d=gallery) --> <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.10/css/all.css" integrity="sha384-+d0P83n9kaQMCwj8F4RJB66tzIwOKmrdb46+porD/OvrJ+37WqIM7UoBtwHO6Nlg" crossorigin="anonymous"> <!-- Custom styles and overrides --> <link href="custom.css" rel="stylesheet"> </head> <body> <nav class="navbar navbar-expand-md fixed-top navbar-dark bg-dark"> <!--Branding icon and text--> <a class="navbar-brand" href="https://worldwind.arc.nasa.gov/web target=_blank"> <img src="images/nasa-logo_32.png" width="30" height="30" class="d-inline-block align-top" alt=""> WorldWindJS </a> <!--Hamburger menu displayed on small screens/windows--> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#main-menu" aria-controls="main-menu" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <!--Main menu content--> <div class="collapse navbar-collapse" id="main-menu"> <ul class="navbar-nav mr-auto"> <!--Layers--> <li class="nav-item"> <a class="nav-link" data-toggle="collapse" href="#layers" role="button"> <span class="fas fa-list" aria-hidden="true"></span> <span class="d-md-none d-lg-inline" aria-hidden="true">Layers</span> </a> </li> <!--Markers--> <li class="nav-item"> <a class="nav-link" data-toggle="collapse" href="#markers" role="button"> <span class="fas fa-map-marker-alt" aria-hidden="true"></span> <span class="d-md-none d-lg-inline" aria-hidden="true">Markers</span> </a> </li> <!--Settings--> <li class="nav-item"> <a class="nav-link" data-toggle="collapse" href="#settings" role="button"> <span class="fas fa-cog" aria-hidden="true"></span> <span class="d-md-none d-lg-inline" aria-hidden="true">Settings</span> </a> </li> </ul> <!--Search Box--> <div class="form-inline"> <input class="form-control mr-sm-2" type="text" placeholder="Search" aria-label="Search"> <button class="btn btn-outline-success" data-toggle="modal" data-target="#preview-dialog"> <span class="fas fa-search" aria-hidden="true"></span> </button> </div> </div> </nav> <!-- Use container-fluid for 100% width and set padding to 0 --> <main role="main" class="container-fluid p-0"> <!-- Globe --> <div id="globe" class="globe"> <!--.d-block ensures the size is correct (prevents a scrollbar from appearing)--> <canvas id="globe-canvas" class="d-block" style="width: 100%; height: 100%; background-color: rgb(36,74,101);"> Try Chrome or FireFox. </canvas> </div> <!--Panels--> <div class="globe-overlay noninteractive w-100"> <div class="card-columns"> <!--Layers--> <div class="collapse" id="layers"> <div class="card globe-card interactive"> <div class="card-header"> <h5 class="card-title"> <span class="fas fa-list" aria-hidden="true"></span> Layers <button type="button" class="close pull-right" aria-label="Close"> <span aria-hidden="true">×</span> </button></h5> </div> <div class="card-body"> <p class="card-text">Layer list goes here.</p> </div> </div> </div> <!--Markers--> <div class="collapse" id="markers"> <div class="card globe-card interactive"> <div class="card-header"> <h5 class="card-title"> <span class="fas fa-map-marker-alt" aria-hidden="true"></span> Markers <button type="button" class="close pull-right" aria-label="Close"> <span aria-hidden="true">×</span> </button></h5> </div> <div class="card-body"> <p class="card-text">Marker list goes here.</p> </div> </div> </div> <!--Settings--> <div class="collapse" id="settings"> <div class="card globe-card interactive"> <div class="card-header"> <h5 class="card-title"> <span class="fas fa-cog" aria-hidden="true"></span> Settings <button type="button" class="close pull-right" aria-label="Close"> <span aria-hidden="true">×</span> </button></h5> </div> <div class="card-body"> <p class="card-text">Settings go here.</p> </div> </div> </div> </div> </div> <!--Search Preview Dialog--> <div id="preview"> <div id="preview-dialog" class="modal" tabindex="-1" role="dialog"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title">Search Results</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <p> Search result go here </p> </div> <div class="modal-footer"> <button type="button" class="btn btn-primary" data-dismiss="modal">Go to</button> <button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button> </div> </div> </div> </div> </div> </main> <!-- JavaScript is placed at the end of the document so the page loads faster --> <script src="https://code.jquery.com/jquery-3.2.1.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script> <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script> <script src="https://unpkg.com/[email protected]/build/dist/worldwind.min.js"></script> <script src="app.js"></script> </body> </html>
body { /*Account for the height of the navbar component*/ padding-top: 3.5rem; } /*Sets the size and style of the globe container*/ .globe { width: 100%; height: calc(100vh - 3.5rem); background-color: black; } /*Sets the position of a container displayed over the globe container*/ .globe-overlay { position: absolute; width: 100%; top: 3.5rem; } Sets the background color of Cards displayed over the globe .globe-card { background: rgba(255, 255, 255, 0.7); } /*When the modal fills the screen it has no margin on top and bottom*/ /*Centers the modal*/ .modal-dialog { margin: 0 auto; } /*Sets the maximum height of the entire modal to 100% of the screen height*/ .modal-content { max-height: 100vh; } /*Sets the maximum height of the modal body to 90% of the screen height*/ .modal-body { max-height: 90vh; } /*Sets the height of a modal's canvas to 30% or 200px*/ .modal-body-canvas { max-height: 200px; height: 30vh; } /*Sets the height of a modal's canvas to 60% minus the height of a footer*/ .modal-body-table { max-height: calc(60vh - 71px); overflow-y: auto; } /* Prevents an element, like a <div/> from consuming user input */ .noninteractive { -webkit-touch-callout: none; -webkit-user-select: none; -khtml-user-select: none; -moz-user-select: none; -ms-user-select: none; -o-user-select: none; pointer-events: none; } /* Allows an element to receive user input */ /* Useful if a parent element is using .noniteractive */ .interactive { -webkit-touch-callout: auto !important; -webkit-user-select: auto !important; -khtml-user-select: auto !important; -moz-user-select: auto !important; -ms-user-select: auto !important; -o-user-select: auto !important; pointer-events: auto !important; }