flights: full CONFIG.flights parameterization (altitude, count, speed, holds, destination weights, contrail chance/alt/life/width) + curved random-destination routing
This commit is contained in:
1 parent
fbac24773a
commit
d0aa86ce9b
10 files changed
+1231
-210
No files matched your search
@@ -1,36 +1,46 @@
|
||||
# Animated Background
|
||||
|
||||
An animated desktop background that runs in a browser. Features:
|
||||
A browser-based animated desktop background: a WebGL flight scene over
|
||||
real terrain, driven by the real sun, moon, stars, and live weather.
|
||||
|
||||
- Time-of-day simulation with realistic color gradients driven by the
|
||||
actual sun position (computed from latitude/longitude via SunCalc).
|
||||
- WebGL flight scene (`vendor/clouds3d.js`): raymarched cloud deck, 3D
|
||||
terrain from Copernicus DEM, real star sky (Yale BSC + Milky Way),
|
||||
moon with phases, animated highway car lights and settlement lights
|
||||
from OpenStreetMap/Overpass at night.
|
||||
- Night brightness coupled to the moon phase (new moon = minimum, full
|
||||
moon = maximum), with a configurable minimum so the night is never
|
||||
pitch-black.
|
||||
- Live weather widget (Open-Meteo) showing current conditions and a
|
||||
4-day forecast (morning, evening, full) at every timestamp.
|
||||
- Configurable units (metric °C+km/h or imperial °F+mph).
|
||||
- Configurable language (with English as the base; translations for
|
||||
German, Italian, Spanish, French, and Russian).
|
||||
- Configurable color theme (Ash, Gruvbox, Nord) - drop a new
|
||||
`*.css` file in the same directory and add an entry to `window.THEMES`
|
||||
to add a new theme.
|
||||
- Customisable location: set `CONFIG.location.lat/lon`, or let the
|
||||
browser's geolocation API pick one up automatically (falls back to
|
||||
the built-in default Passau).
|
||||
- Optional custom location label (`CONFIG.location.label`) that
|
||||
overrides the OpenStreetMap reverse-geocoding lookup.
|
||||
- Configurable digital clock format string using ISO-8601-ish tokens
|
||||
(YYYY, MM, DD, HH, mm, ss, DDD, DDDD, MMM, MMMM, a, A, sss, T, escape
|
||||
sequences \n \t \\, and full weekday/month names via the i18n dict).
|
||||
- Configurable debug panel (toggle collapse/expand with theme, units,
|
||||
and language dropdowns that apply at runtime).
|
||||
## Features
|
||||
|
||||
## Run with Docker
|
||||
- **WebGL flight scene** (`vendor/clouds3d.js`): raymarched cloud deck,
|
||||
3D terrain mesh from real elevation data (Copernicus DEM), satellite
|
||||
or street basemap, figure-eight flight path around the configured
|
||||
location with a vertical bob between **15 and 35 km** flight altitude.
|
||||
- **Real day/night cycle** driven by the actual sun and moon position
|
||||
(SunCalc) for the configured latitude/longitude — or an accelerated
|
||||
24 h simulation (`CONFIG.day`) for wall-decoration purposes.
|
||||
- **Realistic night sky**: ~8700 stars from the Yale Bright Star
|
||||
Catalogue (crisp GL points, size by magnitude, colour by temperature),
|
||||
rotated with the sidereal rate for the site's latitude, plus a Milky
|
||||
Way band and a phase-correct moon.
|
||||
- **Aircraft**: low-poly jets (CC0 model) cruising the region on curved
|
||||
routes between real airfields, rolling a random destination at every
|
||||
take-off - sun-lit silhouettes with contrails by day, strobing position
|
||||
lights by night (all parameters in `CONFIG.flights`).
|
||||
- **Night lights**: animated car lights along the real motorway/road
|
||||
network and pale-yellow settlement lights (OSM place nodes; bigger
|
||||
towns get more and brighter dots), optionally a NASA VIIRS night-lights
|
||||
satellite overlay. All faded in from dusk, density shaped by a
|
||||
rush-hour curve.
|
||||
- **Live weather** (Open-Meteo): current conditions + 4-day forecast
|
||||
widget; the weather code selects the scene's cloud density and colour
|
||||
mood (sunny / cloudy / stormy / night).
|
||||
- **Fully cached, offline-capable**: basemap tiles, elevation grid,
|
||||
Overpass road/place data, star catalogue and the last weather payload
|
||||
live permanently in IndexedDB. Once warm, the scene renders fully
|
||||
offline; a configurable expiry (`CONFIG.tiles.expireDays`) can refresh
|
||||
basemap tiles periodically.
|
||||
- **Location-aware**: set `CONFIG.location.lat/lon`; everything
|
||||
(flight anchor, terrain tiles, sun/moon, weather, star rotation) is
|
||||
computed from it. If the location is omitted, browser geolocation is
|
||||
tried, falling back to the built-in default (London).
|
||||
- Units (°C/°F), six UI languages, CSS-swappable colour themes
|
||||
(Ash/Gruvbox/Nord), configurable clock format, optional debug panel.
|
||||
|
||||
## Run with Docker (recommended)
|
||||
|
||||
```sh
|
||||
docker compose up --build
|
||||
@@ -38,41 +48,131 @@ docker compose up --build
|
||||
|
||||
Then open <http://localhost:58881/>.
|
||||
|
||||
## Run locally
|
||||
The bundled nginx config (`default.conf`) is more than a file server: it
|
||||
provides CORS proxies for the tile sources (`/esri/`, `/carto/`,
|
||||
`/terrarium/`) that the scene needs for basemap and elevation data.
|
||||
A plain static server without these proxies (e.g.
|
||||
`python3 -m http.server 58881`) will run the UI but terrain and map
|
||||
tiles will fail to load.
|
||||
|
||||
The app is a single HTML page. With any static file server:
|
||||
## Single-file build
|
||||
|
||||
`build.py` bundles everything into one self-contained HTML file
|
||||
(`background-standalone.html`) — all scripts, the star catalogue and all
|
||||
theme CSS are inlined, and theme switching keeps working:
|
||||
|
||||
```sh
|
||||
python3 -m http.server 58881
|
||||
python3 build.py # -> background-standalone.html (no sibling files needed)
|
||||
```
|
||||
|
||||
Open <http://localhost:58881/>.
|
||||
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.
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit `config.js` and reload the page:
|
||||
Edit `config.js` and reload. All keys (with defaults):
|
||||
|
||||
```javascript
|
||||
window.CONFIG = {
|
||||
debug: 0, // 0 = hide debug panel, 1 = show
|
||||
theme: 'ash', // 'ash' | 'gruvbox' | 'nord'
|
||||
units: 'metric', // 'metric' | 'imperial'
|
||||
language: 'de', // 'en' | 'de' | 'it' | 'es' | 'fr' | 'ru'
|
||||
language: 'en', // 'en' | 'de' | 'it' | 'es' | 'fr' | 'ru'
|
||||
timeFormat: 'DD. MMMM, YYYY \u2012 HH:mm:SS',
|
||||
location: {
|
||||
lat: 48.5667, // latitude, -90 to +90, north positive
|
||||
lon: 13.4319, // longitude, -180 to +180, east positive
|
||||
label: '' // optional custom place name;
|
||||
// if set, skips reverse-geocoding
|
||||
debug: 0, // 1 = show right-side debug panel
|
||||
units: { temperature: 'C' }, // 'C' | 'F'
|
||||
credits: true, // data-attribution block in info box
|
||||
renderScale: 1, // 0.3..1 internal 3D resolution
|
||||
|
||||
location: { // drives scene anchor, sun/moon, weather
|
||||
lat: 51.5074, // -90..+90, north positive
|
||||
lon: -0.1278, // -180..+180, east positive
|
||||
label: '' // optional name, skips reverse geocoding
|
||||
},
|
||||
orbit: { // omit/null = straight-line flight
|
||||
radiusKm: 15, // circular flight around location;
|
||||
// clamped to ~50 km at zoom 11
|
||||
clockwise: true // turn direction
|
||||
|
||||
day: {
|
||||
simulation: false, // true: run 24 h in cycleSeconds;
|
||||
cycleSeconds: 20, // false: real sun/moon positions
|
||||
fixedTime: null // 'HH:MM' freezes the sim clock at
|
||||
// that time of day (cars, clouds,
|
||||
// weather keep moving); null = flow
|
||||
},
|
||||
weatherSim: false, // true: cycle weather themes, ignore API
|
||||
weatherSimInterval: 30000, // ms per sim step
|
||||
|
||||
clouds: { top: 0.9, bottom: -0.3 },// cloud deck, world units
|
||||
// (1 unit = ~12.9 km at z11 / 48.6 deg N)
|
||||
|
||||
orbit: { // null/omit = straight flight
|
||||
radiusKm: 60, // lemniscate lobe tip (clamped ~190 km)
|
||||
clockwise: true,
|
||||
reorient: true, // random heading at each crossing
|
||||
altBob: { // vertical bob, flight band 15-35 km
|
||||
enabled: true, // false = constant 25 km
|
||||
amp: 0.77, // half-band in world units
|
||||
periodS: 90, // seconds per bob cycle
|
||||
tilt: 0.3 // pitch reaction to climb/descent
|
||||
}
|
||||
},
|
||||
fog: { distanceKm: 120 }, // ground haze; 0/false = off
|
||||
|
||||
terrain: {
|
||||
enabled: true, // false = flat plane
|
||||
exaggeration: 8, // vertical DEM scale factor
|
||||
wireframe: false, // debug: orange mesh edges
|
||||
nightLights: false, // NASA VIIRS city-lights overlay
|
||||
carLights: true, // moving lights on real roads
|
||||
cityLights: true // settlement glow dots
|
||||
},
|
||||
|
||||
flights: { // see section above; all distances km
|
||||
enabled: true,
|
||||
altitudeKm: 14, climbKm: 100, // cruise / climb-descent run
|
||||
count: 84, speedKmh: 850, speedVar: 0.18, minLegKm: 60,
|
||||
holdMinS: 50, holdMaxS: 150, // ground hold at destination
|
||||
wHub: 4, wField: 2, wStrip: 1, // destination roll weights
|
||||
contrailChance: 0.6, // share of aircraft with a trail
|
||||
contrailStartKm: 6, // formation altitude
|
||||
contrailLifeS: 300, // visibility duration
|
||||
contrailWidthM: 310 // full trail width
|
||||
},
|
||||
|
||||
ground: { style: 'satellite' }, // 'satellite' | 'streets'
|
||||
tiles: {
|
||||
expireDays: null, // >0: re-fetch basemap tiles after n days
|
||||
debug: false // tile borders + coords on the ground
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## URL hash parameters
|
||||
|
||||
`http://host:58881/#flight=N&fetch=S`
|
||||
|
||||
- `flight=N|NE|E|SE|S|SW|W|NW` — heading of the straight flight corridor
|
||||
(used when `CONFIG.orbit` is disabled)
|
||||
- `fetch=N|NE|E|SE|S|SW|W|NW` — direction the tile mosaic is prefetched
|
||||
ahead of the camera
|
||||
|
||||
## Time format tokens
|
||||
|
||||
```
|
||||
YYYY 4-digit year (2026) MM month 01-12 (10)
|
||||
DD day 01-31 (07) HH hour 00-23 (14)
|
||||
mm minute 00-59 (35) ss second 00-59 (22)
|
||||
sss millisecond 000-999 (456) a am/pm (pm)
|
||||
A AM/PM (PM)
|
||||
|
||||
MMM month short name (Oct, Okt, Ott, ...)
|
||||
MMMM month full name (October, Oktober, ...)
|
||||
DDD weekday short name (Mon, Mo, Lu, ...)
|
||||
dddd weekday full name (Monday, Montag, ...) lowercase!
|
||||
|
||||
Any other character is emitted verbatim (so a literal T in ISO-8601
|
||||
needs no special token).
|
||||
\n newline \t tab \\ literal backslash
|
||||
```
|
||||
|
||||
## Adding a new language
|
||||
|
||||
Edit `i18n.js` and add entries for each existing key under your new
|
||||
@@ -85,65 +185,43 @@ window.TRANSLATIONS['Sunrise']['xx'] = 'MyTranslation';
|
||||
## Adding a new theme
|
||||
|
||||
Drop a new `*.css` file next to the others and add an entry to
|
||||
`window.THEMES`:
|
||||
`window.THEMES` in `config.js`:
|
||||
|
||||
```javascript
|
||||
window.THEMES['mytheme'] = 'mytheme.css';
|
||||
```
|
||||
|
||||
## Time format tokens
|
||||
|
||||
```
|
||||
YYYY 4-digit year (2026)
|
||||
MM month 01-12 (10)
|
||||
DD day 01-31 (07)
|
||||
HH hour 00-23 (24h) (14)
|
||||
mm minute 00-59 (35) lowercase!
|
||||
ss second 00-59 (22) lowercase!
|
||||
sss millisecond 000-999 (456)
|
||||
a am/pm (lowercase) (pm)
|
||||
A AM/PM (uppercase) (PM)
|
||||
T literal 'T'
|
||||
|
||||
MMM month short name (Oct, Okt, Ott, ...)
|
||||
MMMM month full name (October, Oktober, ...)
|
||||
DDD weekday short name (Mon, Mo, Lu, ...)
|
||||
DDDD weekday full name (Monday, Montag, ...)
|
||||
|
||||
\n newline
|
||||
\t tab
|
||||
\\ literal backslash
|
||||
```
|
||||
|
||||
## Files
|
||||
|
||||
```
|
||||
.
|
||||
├── background.html the page (formerly index.html)
|
||||
├── background.html the page (UI, weather, day/night driver)
|
||||
├── config.js user-facing configuration
|
||||
├── i18n.js translation strings (en/de/it/es/fr/ru)
|
||||
├── ash.css default color theme
|
||||
├── gruvbox.css alternative color theme
|
||||
├── nord.css alternative color theme
|
||||
├── vendor/ vendored third-party files (no network needed)
|
||||
│ ├── clouds3d.js WebGL scene: raymarched clouds, 3D terrain,
|
||||
│ │ real sun/moon/stars, car + city lights
|
||||
├── vendor/
|
||||
│ ├── clouds3d.js WebGL scene renderer (clouds, terrain, sky, lights)
|
||||
│ ├── suncalc.js ISC (SunCalc by mourner)
|
||||
│ ├── stars.json Yale Bright Star Catalogue subset
|
||||
│ └── LICENSE per-library license attributions
|
||||
├── default.conf nginx server config (port 58881, tile CORS proxies)
|
||||
├── default.conf nginx config: port 58881 + tile CORS proxies
|
||||
├── build.py single-file HTML bundler (see "Single-file build")
|
||||
├── Dockerfile builds nginx:alpine image
|
||||
└── docker-compose.yml one-service Compose file
|
||||
├── docker-compose.yml one-service Compose file
|
||||
└── LICENSE MIT (application code)
|
||||
```
|
||||
|
||||
## Licenses
|
||||
## Licenses & data attribution
|
||||
|
||||
- **Background application code**: MIT
|
||||
- **Background application code**: MIT (see `LICENSE`)
|
||||
- **SunCalc** (vendored): ISC - <https://github.com/mourner/suncalc>
|
||||
- **Open-Meteo** (weather API): CC BY 4.0 - <https://open-meteo.com/>
|
||||
- **OpenStreetMap** (basemap tiles, Overpass road/place data): ODbL -
|
||||
<https://www.openstreetmap.org/copyright>
|
||||
- **Copernicus DEM** (terrain via terrarium tiles): open data
|
||||
- **OpenStreetMap** (basemap tiles via ESRI/Carto, Overpass road and
|
||||
place data): ODbL - <https://www.openstreetmap.org/copyright>
|
||||
- **Copernicus DEM** (terrain via Mapzen terrarium tiles): open data
|
||||
- **NASA GIBS VIIRS** (optional night-lights overlay): public domain
|
||||
- **Yale Bright Star Catalogue** (star positions, via `vendor/stars.json`)
|
||||
- **OpenStreetMap Nominatim** (reverse geocoding): ODbL -
|
||||
<https://nominatim.org/release/>
|
||||
<https://nominatim.org/release/>
|
||||
Reference in new issue
Block a user