standalone without our server: basemap and DEM load from the CORS-enabled upstreams, same-origin proxy only when a probe proves it exists; drop dead kumi.systems mirror
This commit is contained in:
1 parent
3395ac8f8e
commit
499c00d8b1
3 files changed
+62
-19
No files matched your search
@@ -68,8 +68,12 @@ The bundled nginx config (`default.conf`) is more than a file server:
|
||||
- `Cache-Control: no-store` for HTML and JS, so a changed `CONFIG` takes effect
|
||||
on reload.
|
||||
|
||||
A plain static server without these proxies (e.g. `python3 -m http.server
|
||||
58881`) runs the UI, but terrain, basemap and road data will not load.
|
||||
The proxies are a convenience, not a requirement: every data source is also
|
||||
reachable directly from the browser (ESRI, the AWS elevation bucket and the
|
||||
Overpass mirrors all answer cross-origin requests), and the page probes for
|
||||
`/terrarium/` and `/esri/...` at start-up and switches to the proxy only when
|
||||
this same-origin proxy actually exists. Running the files from any static
|
||||
server therefore works as well - just without the nginx-side Overpass cache.
|
||||
|
||||
## Single-file build
|
||||
|
||||
@@ -86,10 +90,14 @@ python3 build.py --check # build to a temp file and verify, write not
|
||||
`--check` fails if anything is left that would need a sibling file (an external
|
||||
`<script src>` or a CSS `<link>`).
|
||||
|
||||
Runtime *data* is still fetched at load (tiles, Overpass, weather): serve the
|
||||
file from the Docker image for the full experience. Opened via `file://` or a
|
||||
proxy-less server it renders sky, clouds and UI with an "OFFLINE"-labelled
|
||||
ground grid instead of basemap tiles.
|
||||
Runtime *data* is fetched at load, but from public sources only: ESRI basemap
|
||||
tiles, the AWS elevation tiles and the Overpass mirrors are all CORS-enabled,
|
||||
and Open-Meteo needs no key. So the built file runs on its own - from any
|
||||
static server, and even opened directly via `file://`. Serving it from the
|
||||
Docker image additionally gives the nginx proxies and the 30-day Overpass
|
||||
cache, which is the gentlest option for the upstreams. If a source is
|
||||
unreachable, the scene degrades instead of failing: an "OFFLINE"-labelled
|
||||
ground grid in place of basemap tiles.
|
||||
|
||||
## Configuration
|
||||
|
||||
|
||||
@@ -15,12 +15,11 @@ What gets inlined:
|
||||
(window.__inlineThemeCss, so
|
||||
theme switching works offline)
|
||||
|
||||
The result needs no sibling files. Runtime DATA is still fetched on load:
|
||||
basemap and elevation tiles, Overpass road/settlement cells and the Open-Meteo
|
||||
weather API. Serve the file from the same nginx as the development site (its
|
||||
CORS proxies make the tiles reachable) or open it with a warm IndexedDB cache
|
||||
for fully offline rendering. Opened via file:// it still runs sky, clouds,
|
||||
terrain shading and the whole UI, just without the textured ground.
|
||||
The result needs no sibling files and no server of ours: basemap tiles, the
|
||||
elevation tiles and the Overpass mirrors are all CORS-enabled public sources,
|
||||
so the file runs from any static host or straight from disk (file://). The
|
||||
bundled nginx is optional - it adds the same-origin proxies and a 30-day
|
||||
Overpass cache, which is the gentlest way to hit those upstreams.
|
||||
|
||||
The build fails loudly if any external script or stylesheet reference survives.
|
||||
"""
|
||||
|
||||
Vendored
+43
-7
@@ -826,12 +826,20 @@ function init(canvas) {
|
||||
// Tile source per CONFIG.ground.style:
|
||||
// 'streets' - ESRI World_Street_Map (place names), /esri/streets/
|
||||
// 'satellite' - ESRI World_Imagery (no labels), /esri/imagery/
|
||||
// Both are z11 {z}/{y}/{x}.jpg via the nginx CORS proxy. The IndexedDB
|
||||
// id carries a style prefix so both styles can coexist in the cache.
|
||||
// Both are z11 {z}/{y}/{x}.jpg (y before x). ESRI answers cross-origin
|
||||
// GETs with Access-Control-Allow-Origin: *, so the standalone build needs
|
||||
// no server at all; the same-origin nginx paths are used instead when this
|
||||
// page has them (proxy cache, friendlier to the upstream). The IndexedDB id
|
||||
// carries a style prefix so both styles can coexist in the cache.
|
||||
var GROUND_STYLE_CFG = (window.CONFIG && window.CONFIG.ground &&
|
||||
window.CONFIG.ground.style) || 'streets';
|
||||
var GROUND_STYLE = GROUND_STYLE_CFG === 'satellite' ? 'satellite' : 'streets';
|
||||
var GROUND_TILE_URL = GROUND_STYLE === 'satellite' ? '/esri/imagery/' : '/esri/streets/';
|
||||
var GROUND_TILE_DIRECT = (GROUND_STYLE === 'satellite')
|
||||
? 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/'
|
||||
: 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer/tile/';
|
||||
var GROUND_TILE_PROXY = (GROUND_STYLE === 'satellite') ? '/esri/imagery/' : '/esri/streets/';
|
||||
// direct by default: works from any origin, including a plain file:// open
|
||||
var GROUND_TILE_URL = GROUND_TILE_DIRECT;
|
||||
var GROUND_TILE_ID_PREFIX = GROUND_STYLE === 'satellite' ? 'sat/' : '';
|
||||
// Debug tile overlays (border + N/S + x/y labels) - off unless
|
||||
// CONFIG.tiles.debug is true.
|
||||
@@ -1172,9 +1180,31 @@ window.BackgroundCache = {
|
||||
}
|
||||
};
|
||||
|
||||
// ---- tile source selection ---------------------------------------------
|
||||
// Start from the public upstreams so the page works anywhere, then switch a
|
||||
// source over to the same-origin proxy if a probe shows it is really served
|
||||
// by our nginx (an image content-type is required, so a SPA fallback that
|
||||
// answers 200 + HTML for every path cannot hijack the switch).
|
||||
var _tileProxyChecked = false;
|
||||
function tileProbeProxy() {
|
||||
if (_tileProxyChecked) return;
|
||||
_tileProxyChecked = true;
|
||||
if (location.protocol === 'file:') return;
|
||||
function probe(path, apply) {
|
||||
fetch(path, { method: 'HEAD' }).then(function (r) {
|
||||
var type = (r.headers.get('Content-Type') || '').toLowerCase();
|
||||
if (r.ok && type.indexOf('image/') === 0) {
|
||||
apply();
|
||||
console.log('[clouds3d] tiles: using dev proxy ' + path);
|
||||
}
|
||||
}, function () {});
|
||||
}
|
||||
probe(ELEV_TILE_PROXY + '11/0/0.png', function () { ELEV_TILE_URL = ELEV_TILE_PROXY; });
|
||||
probe(GROUND_TILE_PROXY + GROUND_TILE_Z + '/0/0.jpg',
|
||||
function () { GROUND_TILE_URL = GROUND_TILE_PROXY; });
|
||||
}
|
||||
function fetchTileBlob(tileX, tileY) {
|
||||
// ESRI World_Street_Map format: {z}/{y}/{x}.jpg via local
|
||||
// proxy. (y before x, jpg not png)
|
||||
// ESRI World_Street_Map format: {z}/{y}/{x}.jpg (y before x, jpg not png)
|
||||
return fetch(GROUND_TILE_URL + GROUND_TILE_Z + '/' + tileY + '/' + tileX + '.jpg')
|
||||
.then(function (r) {
|
||||
if (!r.ok) throw new Error('tile http ' + r.status);
|
||||
@@ -1471,7 +1501,14 @@ function recenterGroundMosaic(centerTileX, centerTileY, dLng, dPerp) {
|
||||
var ELEV_Z = 10;
|
||||
var ELEV_TILES_PER = 1 << (11 - ELEV_Z); // z11 tiles covered per DEM tile
|
||||
var ELEV_UNIT_PX = 256 / ELEV_TILES_PER; // canvas px per z11 tile
|
||||
var ELEV_TILE_URL = '/terrarium/';
|
||||
// elevation-tiles-prod (AWS) answers cross-origin GETs with CORS, so the
|
||||
// DEM also loads without our server; /terrarium/ is preferred when present.
|
||||
var ELEV_TILE_DIRECT = 'https://s3.amazonaws.com/elevation-tiles-prod/terrarium/';
|
||||
var ELEV_TILE_PROXY = '/terrarium/';
|
||||
var ELEV_TILE_URL = ELEV_TILE_DIRECT;
|
||||
// (the probe needs both URL pairs assigned, so it runs here, not at the
|
||||
// ground-source block)
|
||||
tileProbeProxy();
|
||||
var elevCanvas = null;
|
||||
var elevCtx = null;
|
||||
var elevTexture = null;
|
||||
@@ -2098,7 +2135,6 @@ var CAR_QUERIES = carCells('geo/mw11', CAR_MOTORWAY_RX, 46.8, 9.4, 50.1, 13.4, 1
|
||||
// the proxy is actually there (see opProbeProxy), otherwise they are dropped.
|
||||
var OP_PUBLIC = [
|
||||
'https://overpass-api.de/api/interpreter',
|
||||
'https://overpass.kumi.systems/api/interpreter',
|
||||
'https://maps.mail.ru/osm/tools/overpass/api/interpreter'
|
||||
];
|
||||
var OP_PROXY = ['/overpass/api/interpreter', '/overpass/mail/interpreter'];
|
||||
|
||||
Reference in new issue
Block a user