mirror of
https://github.com/openglobus/openglobus.git
synced 2025-12-08 19:25:27 +00:00
276 lines
9.7 KiB
JavaScript
276 lines
9.7 KiB
JavaScript
/**
|
|
* @module og/Globe
|
|
*/
|
|
|
|
"use strict";
|
|
|
|
import { CompassButton } from "./control/CompassButton.js";
|
|
import { EarthCoordinates } from "./control/EarthCoordinates.js";
|
|
import { EarthNavigation } from "./control/EarthNavigation.js";
|
|
import { MouseNavigation } from "./control/MouseNavigation.js";
|
|
import { ScaleControl } from "./control/ScaleControl.js";
|
|
import { Sun } from "./control/Sun.js";
|
|
import { TouchNavigation } from "./control/TouchNavigation.js";
|
|
import { ZoomControl } from "./control/ZoomControl.js";
|
|
import { Renderer } from "./renderer/Renderer.js";
|
|
import { Planet } from "./scene/Planet.js";
|
|
import { EmptyTerrain } from "./terrain/EmptyTerrain.js";
|
|
import { isEmpty } from "./utils/shared.js";
|
|
import { Handler } from "./webgl/Handler.js";
|
|
|
|
/** @const {string} */
|
|
const CANVAS_ID_PREFIX = "globus_viewport_";
|
|
/** @const {string} */
|
|
const PLANET_NAME_PREFIX = "globus_planet_";
|
|
|
|
/**
|
|
* Creates a WebGL context with globe.
|
|
* @class
|
|
*
|
|
* @example <caption>Basic initialization</caption>
|
|
* globus = new og.Globe({
|
|
* 'atmosphere': false,
|
|
* 'target': 'globus',
|
|
* 'name': 'Earth',
|
|
* 'controls': [
|
|
* new og.control.MouseNavigation({ autoActivate: true }),
|
|
* new og.control.KeyboardNavigation({ autoActivate: true }),
|
|
* new og.control.EarthCoordinates({ autoActivate: true, center: false }),
|
|
* new og.control.LayerSwitcher({ autoActivate: true }),
|
|
* new og.control.ZoomControl({ autoActivate: true }),
|
|
* new og.control.TouchNavigation({ autoActivate: true }),
|
|
* new og.control.Sun({ autoActivate: true })
|
|
* ],
|
|
* 'terrain': new og.terrain.GlobusTerrain(),
|
|
* 'layers': [
|
|
* new og.layer.XYZ("OpenStreetMap", { isBaseLayer: true, url: "http://b.tile.openstreetmap.org/{z}/{x}/{y}.png", visibility: true, attribution: 'Data @ <a href="http://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="http://www.openstreetmap.org/copyright">ODbL</a>' })
|
|
* ],
|
|
* 'autoActivate': true
|
|
* });
|
|
*
|
|
* @param {object} options - Options:
|
|
* @param {string} options.target - HTML element id where planet canvas have to be created.
|
|
* @param {RenderNode} [options.skybox] - Render skybox. null - default.
|
|
* @param {string} [options.name] - Planet name. Default is unic identifier.
|
|
* @param {Terrain} [options.terrain] - Terrain provider. Default no terrain - og.terrain.EmptyTerrain.
|
|
* @param {Array.<control.Control>} [options.controls] - Renderer controls array.
|
|
* @param {Array.<Layer>} [options.layers] - Planet layers.
|
|
* @param {Extent} [options.viewExtent] - Viewable starting extent.
|
|
* @param {boolean} [options.autoActivate] - Globe rendering auto activation flag. True is default.
|
|
* @param {DOMElement} [options.attributionContainer] - Container for attribution list.
|
|
* @param {Number} [options.maxGridSize] = Maximal segment grid size. 128 is default
|
|
* @param {boolean} [options.useSpecularTexture] - use specular water mask
|
|
* @param {boolean} [options.useNightTexture] - show night cities
|
|
* @param {Number} [options.maxEqualZoomAltitude=850000.0] - Maximal altitude since segments on the screen bacame the same zoom level
|
|
* @param {Number} [options.minEqualZoomAltitude=10000.0] - Minimal altitude since segments on the screen bacame the same zoom level
|
|
* @param {Number} [options.minEqualZoomCameraSlope=0.8] - Minimal camera slope above te globe where segments on the screen bacame the same zoom level
|
|
*/
|
|
|
|
class Globe {
|
|
/**
|
|
* @param {*} options
|
|
*/
|
|
constructor(options) {
|
|
// Canvas creation
|
|
var _canvasId = CANVAS_ID_PREFIX + Globe._staticCounter++;
|
|
|
|
this._canvas = document.createElement("canvas");
|
|
this._canvas.id = _canvasId;
|
|
this._canvas.style.width = "100%";
|
|
this._canvas.style.height = "100%";
|
|
this._canvas.style.display = "block";
|
|
this._canvas.style.opacity = "0.0";
|
|
this._canvas.style.transition = "opacity 1.0s";
|
|
|
|
/**
|
|
* Dom element where WebGL canvas creates
|
|
* @public
|
|
* @type {Element}
|
|
*/
|
|
if (options.target instanceof HTMLElement) {
|
|
this.div = options.target;
|
|
} else {
|
|
this.div =
|
|
document.getElementById(options.target) || document.querySelector(options.target);
|
|
}
|
|
|
|
this.div.appendChild(this._canvas);
|
|
this.div.classList.add("ogViewport");
|
|
|
|
function _disableWheel(e) {
|
|
e.preventDefault();
|
|
}
|
|
|
|
this.div.onmouseenter = function () {
|
|
document.addEventListener("mousewheel", _disableWheel, {
|
|
capture: false,
|
|
passive: false
|
|
});
|
|
};
|
|
this.div.onmouseleave = function () {
|
|
document.removeEventListener("mousewheel", _disableWheel);
|
|
};
|
|
|
|
/**
|
|
* Interface for the renderer context(events, input states, renderer nodes etc.)
|
|
* @public
|
|
* @type {Renderer}
|
|
*/
|
|
this.renderer = new Renderer(
|
|
new Handler(_canvasId, {
|
|
context: {
|
|
alpha: false,
|
|
antialias: false,
|
|
powerPreference: "high-performance"
|
|
}
|
|
}),
|
|
{
|
|
autoActivate: false
|
|
}
|
|
);
|
|
this.renderer.initialize();
|
|
this.renderer.div = this.div;
|
|
this.renderer.div.attributions = document.createElement("div");
|
|
if (options.attributionContainer) {
|
|
options.attributionContainer.appendChild(this.renderer.div.attributions);
|
|
} else {
|
|
this.renderer.div.attributions.classList.add("ogAttribution");
|
|
this.div.appendChild(this.renderer.div.attributions);
|
|
}
|
|
|
|
// Skybox
|
|
if (options.skybox) {
|
|
this.renderer.addNode(options.skybox);
|
|
}
|
|
|
|
/**
|
|
* Planet node name. Access with this.renderer.<name>
|
|
* @private
|
|
* @type {String}
|
|
*/
|
|
this._planetName = options.name ? options.name : PLANET_NAME_PREFIX + Globe._staticCounter;
|
|
|
|
if (options.atmosphere) {
|
|
/**
|
|
* Render node renders a planet.
|
|
* @public
|
|
* @type {Planet|og.scene.PlanetAtmosphere}
|
|
*/
|
|
// TODO:
|
|
} else {
|
|
this.planet = new Planet({
|
|
name: this._planetName,
|
|
ellipsoid: options.ellipsoid,
|
|
maxGridSize: options.maxGridSize,
|
|
useNightTexture: options.useNightTexture,
|
|
useSpecularTexture: options.useSpecularTexture,
|
|
minAltitude: options.minAltitude,
|
|
maxAltitude: options.maxAltitude,
|
|
maxEqualZoomAltitude: options.maxEqualZoomAltitude,
|
|
minEqualZoomAltitude: options.minEqualZoomAltitude,
|
|
minEqualZoomCameraSlope: options.minEqualZoomCameraSlope
|
|
});
|
|
}
|
|
|
|
// Attach terrain provider
|
|
if (options.terrain) {
|
|
this.planet.setTerrain(options.terrain);
|
|
} else {
|
|
this.planet.setTerrain(new EmptyTerrain());
|
|
}
|
|
|
|
this.renderer.addNode(this.planet);
|
|
|
|
// Add controls
|
|
if (options.controls) {
|
|
this.planet.addControls(options.controls);
|
|
} else {
|
|
this.planet.addControls([
|
|
new ZoomControl(),
|
|
options.useEarthNavigation
|
|
? new EarthNavigation()
|
|
: new MouseNavigation({
|
|
minSlope: options.minSlope
|
|
}),
|
|
new TouchNavigation(),
|
|
new EarthCoordinates(),
|
|
new ScaleControl(),
|
|
new CompassButton(options)
|
|
]);
|
|
}
|
|
|
|
var _controls = this.renderer.controls;
|
|
for (var i in _controls) {
|
|
if (_controls[i] instanceof Sun) {
|
|
this.sun = _controls[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!this.sun) {
|
|
this.sun = new Sun();
|
|
this.planet.addControl(this.sun);
|
|
}
|
|
|
|
if (options.sun) {
|
|
if (options.sun.active !== undefined && !options.sun.active) {
|
|
this.sun.deactivate();
|
|
}
|
|
}
|
|
|
|
if (options.layers) {
|
|
this.planet.addLayers(options.layers);
|
|
}
|
|
|
|
// TODO: view center, altitude, extent
|
|
let ve = options.viewExtent;
|
|
if (ve) {
|
|
if (ve instanceof Array) {
|
|
this.planet.viewExtentArr(ve);
|
|
} else {
|
|
this.planet.viewExtent(ve);
|
|
}
|
|
}
|
|
|
|
this._opacityCounter = 0;
|
|
this._fadeHandler = null;
|
|
this._stopHandler = null;
|
|
|
|
// Run!
|
|
if (options.autoActivate || isEmpty(options.autoActivate)) {
|
|
this.renderer.start();
|
|
this.fadeIn();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Starts screen brightness fading in effect by the duration time.
|
|
* @public
|
|
*/
|
|
fadeIn() {
|
|
this._canvas.style.opacity = 1.0;
|
|
}
|
|
|
|
/**
|
|
* Starts screen brightness fading out effect by the duration time.
|
|
* @public
|
|
* @param {number} duration - Fadeout duration time.
|
|
*/
|
|
fadeOut() {
|
|
this._canvas.style.opacity = 0.0;
|
|
}
|
|
|
|
static get _staticCounter() {
|
|
if (!this._counter && this._counter !== 0) {
|
|
this._counter = 0;
|
|
}
|
|
return this._counter;
|
|
}
|
|
|
|
static set _staticCounter(n) {
|
|
this._counter = n;
|
|
}
|
|
}
|
|
|
|
export { Globe };
|