generated from Labyricorn/labyricorn-project-template
565 lines
20 KiB
JavaScript
565 lines
20 KiB
JavaScript
/*
|
|
* Planetarium — exhibit behaviour.
|
|
*
|
|
* Owns the sky model, the ephemeris, the canvas rendering, and the native
|
|
* controls. No contract awareness: no target IDs, no events, no revisions.
|
|
*
|
|
* The exhibit's own services (absolute setters and real actions) are what
|
|
* the contract layer binds to, so the native UI and a future host share one
|
|
* code path.
|
|
*/
|
|
(function () {
|
|
'use strict';
|
|
|
|
var TAU = Math.PI * 2;
|
|
|
|
var CATALOG = [
|
|
{ id: 'orion', label: 'Orion', stars: 9, brightness: 1.0, hue: '#cfe4ff' },
|
|
{ id: 'cygnus', label: 'Cygnus', stars: 7, brightness: 0.85, hue: '#dbe8ff' },
|
|
{ id: 'scorpius', label: 'Scorpius', stars: 8, brightness: 0.95, hue: '#ffe0c4' },
|
|
{ id: 'ursa-major', label: 'Ursa Major', stars: 7, brightness: 0.8, hue: '#e6f0ff' },
|
|
{ id: 'cassiopeia', label: 'Cassiopeia', stars: 5, brightness: 0.75, hue: '#f0e6ff' },
|
|
{ id: 'lyra', label: 'Lyra', stars: 6, brightness: 0.9, hue: '#e8f4ff' }
|
|
];
|
|
|
|
var BODIES = [
|
|
{ id: 'moon', label: 'Moon', radius: 0.055, period: 0.09, color: '#e8eef7', phase: 0.2 },
|
|
{ id: 'mars', label: 'Mars', radius: 0.085, period: 0.16, color: '#e07a52', phase: 1.1 },
|
|
{ id: 'jupiter', label: 'Jupiter', radius: 0.115, period: 0.27, color: '#e6c79a', phase: 2.4 },
|
|
{ id: 'saturn', label: 'Saturn', radius: 0.145, period: 0.41, color: '#e8d9a8', phase: 4.0, ring: true }
|
|
];
|
|
|
|
var FILTERS = [
|
|
{ id: 'none', label: 'None', tint: null, gain: 1.0 },
|
|
{ id: 'light-pollution', label: 'Light pollution', tint: '#3a2a1a', gain: 0.55 },
|
|
{ id: 'h-alpha', label: 'H-alpha', tint: '#5a1020', gain: 0.8 },
|
|
{ id: 'oxygen-iii', label: 'Oxygen III', tint: '#0d3a4a', gain: 0.8 }
|
|
];
|
|
|
|
var MAX_MAGNITUDE = 6.0;
|
|
var MIN_MAGNITUDE = 1.0;
|
|
|
|
function clamp(v, lo, hi) { return v < lo ? lo : (v > hi ? hi : v); }
|
|
|
|
function findById(list, id) {
|
|
for (var i = 0; i < list.length; i++) if (list[i].id === id) return list[i];
|
|
return null;
|
|
}
|
|
|
|
/* Deterministic pseudo-random so a constellation always looks the same. */
|
|
function hash(n) {
|
|
var x = Math.sin(n * 127.1 + 311.7) * 43758.5453;
|
|
return x - Math.floor(x);
|
|
}
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Sky model
|
|
* ------------------------------------------------------------------ */
|
|
|
|
function Sky() {
|
|
this.constellation = 'orion';
|
|
this.magnitudeLimit = 4.5;
|
|
this.azimuth = 0.25;
|
|
this.altitude = 0.5;
|
|
this.timeScale = 0.5;
|
|
this.filter = 'none';
|
|
this.tracking = true;
|
|
this.paused = false;
|
|
this.skyTime = 0;
|
|
this.stars = [];
|
|
this._buildStars();
|
|
}
|
|
|
|
Sky.prototype._buildStars = function () {
|
|
this.stars = [];
|
|
var count = 420;
|
|
for (var i = 0; i < count; i++) {
|
|
var mag = MIN_MAGNITUDE + hash(i * 3.1) * (MAX_MAGNITUDE - MIN_MAGNITUDE);
|
|
this.stars.push({
|
|
x: hash(i * 1.7),
|
|
y: hash(i * 2.3) * 0.92,
|
|
mag: mag,
|
|
twinkle: hash(i * 5.9) * TAU,
|
|
hue: hash(i * 7.3) > 0.82 ? '#ffd9b0' : (hash(i * 9.1) > 0.7 ? '#c9d8ff' : '#ffffff')
|
|
});
|
|
}
|
|
};
|
|
|
|
Sky.prototype.step = function (dt) {
|
|
if (this.paused) return;
|
|
this.skyTime += dt * this.timeScale;
|
|
};
|
|
|
|
/** Position of a body on the sky dome, in normalised 0..1 coordinates. */
|
|
Sky.prototype.bodyPosition = function (body) {
|
|
var angle = body.phase + this.skyTime * TAU * body.period;
|
|
var cx = 0.5 + (this.azimuth - 0.5) * 0.6;
|
|
var cy = 0.5 + (this.altitude - 0.5) * 0.6;
|
|
return {
|
|
x: cx + Math.cos(angle) * body.radius * 3.2,
|
|
y: cy + Math.sin(angle) * body.radius * 1.9
|
|
};
|
|
};
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Rendering
|
|
* ------------------------------------------------------------------ */
|
|
|
|
function Renderer(canvas, sky) {
|
|
this.canvas = canvas;
|
|
this.ctx = canvas.getContext('2d');
|
|
this.sky = sky;
|
|
this.width = 0;
|
|
this.height = 0;
|
|
this.resize();
|
|
}
|
|
|
|
Renderer.prototype.resize = function () {
|
|
var rect = this.canvas.getBoundingClientRect();
|
|
var dpr = window.devicePixelRatio || 1;
|
|
this.width = Math.max(1, Math.round(rect.width));
|
|
this.height = Math.max(1, Math.round(rect.height));
|
|
this.canvas.width = Math.round(this.width * dpr);
|
|
this.canvas.height = Math.round(this.height * dpr);
|
|
this.ctx.setTransform(dpr, 0, 0, dpr, 0, 0);
|
|
};
|
|
|
|
Renderer.prototype.draw = function () {
|
|
var ctx = this.ctx;
|
|
var w = this.width;
|
|
var h = this.height;
|
|
var sky = this.sky;
|
|
var filter = findById(FILTERS, sky.filter);
|
|
var constellation = findById(CATALOG, sky.constellation);
|
|
|
|
ctx.clearRect(0, 0, w, h);
|
|
|
|
/* Sky dome. */
|
|
var grad = ctx.createRadialGradient(w * 0.5, h * 0.55, 0, w * 0.5, h * 0.55, Math.max(w, h) * 0.75);
|
|
grad.addColorStop(0, '#0b1226');
|
|
grad.addColorStop(1, '#03050c');
|
|
ctx.fillStyle = grad;
|
|
ctx.fillRect(0, 0, w, h);
|
|
|
|
/* Horizon glow. */
|
|
var horizon = ctx.createLinearGradient(0, h * 0.72, 0, h);
|
|
horizon.addColorStop(0, 'rgba(20,40,80,0)');
|
|
horizon.addColorStop(1, 'rgba(30,60,110,0.35)');
|
|
ctx.fillStyle = horizon;
|
|
ctx.fillRect(0, h * 0.72, w, h * 0.28);
|
|
|
|
/* Stars, filtered by the magnitude limit. */
|
|
for (var i = 0; i < sky.stars.length; i++) {
|
|
var s = sky.stars[i];
|
|
if (s.mag > sky.magnitudeLimit) continue;
|
|
var norm = 1 - (s.mag - MIN_MAGNITUDE) / (MAX_MAGNITUDE - MIN_MAGNITUDE);
|
|
var alpha = clamp(norm * 0.95 + 0.05, 0, 1) * filter.gain;
|
|
var twinkle = 0.85 + Math.sin(sky.skyTime * 2.4 + s.twinkle) * 0.15;
|
|
var r = 0.6 + norm * 1.9;
|
|
|
|
ctx.globalAlpha = clamp(alpha * twinkle, 0, 1);
|
|
ctx.fillStyle = s.hue;
|
|
ctx.beginPath();
|
|
ctx.arc(s.x * w, s.y * h, r, 0, TAU);
|
|
ctx.fill();
|
|
}
|
|
ctx.globalAlpha = 1;
|
|
|
|
/* The selected constellation, drawn as a connected figure. */
|
|
var baseX = (0.5 + (sky.azimuth - 0.5) * 0.7) * w;
|
|
var baseY = (0.42 + (sky.altitude - 0.5) * 0.5) * h;
|
|
var scale = Math.min(w, h) * 0.16;
|
|
var points = [];
|
|
for (var k = 0; k < constellation.stars; k++) {
|
|
var angle = (k / constellation.stars) * TAU + hash(k * 4.4) * 0.6;
|
|
var dist = 0.35 + hash(k * 6.1) * 0.65;
|
|
points.push({
|
|
x: baseX + Math.cos(angle) * dist * scale,
|
|
y: baseY + Math.sin(angle) * dist * scale * 0.7
|
|
});
|
|
}
|
|
|
|
ctx.strokeStyle = 'rgba(150,200,255,' + (0.28 * filter.gain) + ')';
|
|
ctx.lineWidth = 1;
|
|
ctx.beginPath();
|
|
for (var p = 0; p < points.length; p++) {
|
|
var next = points[(p + 1) % points.length];
|
|
ctx.moveTo(points[p].x, points[p].y);
|
|
ctx.lineTo(next.x, next.y);
|
|
}
|
|
ctx.stroke();
|
|
|
|
for (var q = 0; q < points.length; q++) {
|
|
ctx.fillStyle = constellation.hue;
|
|
ctx.globalAlpha = clamp(constellation.brightness * filter.gain, 0, 1);
|
|
ctx.beginPath();
|
|
ctx.arc(points[q].x, points[q].y, 2.4, 0, TAU);
|
|
ctx.fill();
|
|
}
|
|
ctx.globalAlpha = 1;
|
|
|
|
/* Label the constellation with textContent-equivalent canvas text. */
|
|
ctx.fillStyle = 'rgba(190,220,255,0.75)';
|
|
ctx.font = '600 12px "Segoe UI", sans-serif';
|
|
ctx.fillText(constellation.label, baseX - scale * 0.5, baseY + scale * 1.15);
|
|
|
|
/* Solar-system bodies. */
|
|
for (var b = 0; b < BODIES.length; b++) {
|
|
var body = BODIES[b];
|
|
var pos = sky.bodyPosition(body);
|
|
var bx = pos.x * w;
|
|
var by = pos.y * h;
|
|
var br = body.radius * Math.min(w, h) * 0.5;
|
|
|
|
ctx.globalAlpha = clamp(filter.gain, 0, 1);
|
|
ctx.fillStyle = body.color;
|
|
ctx.beginPath();
|
|
ctx.arc(bx, by, br, 0, TAU);
|
|
ctx.fill();
|
|
|
|
if (body.ring) {
|
|
ctx.strokeStyle = 'rgba(232,217,168,0.7)';
|
|
ctx.lineWidth = 2;
|
|
ctx.beginPath();
|
|
ctx.ellipse(bx, by, br * 1.9, br * 0.6, 0.4, 0, TAU);
|
|
ctx.stroke();
|
|
}
|
|
|
|
ctx.fillStyle = 'rgba(200,220,255,0.6)';
|
|
ctx.font = '11px "Segoe UI", sans-serif';
|
|
ctx.fillText(body.label, bx + br + 5, by + 4);
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
|
|
/* Filter tint over the whole frame. */
|
|
if (filter.tint) {
|
|
ctx.globalAlpha = 0.22;
|
|
ctx.fillStyle = filter.tint;
|
|
ctx.fillRect(0, 0, w, h);
|
|
ctx.globalAlpha = 1;
|
|
}
|
|
|
|
/* Tracking reticle. */
|
|
if (sky.tracking) {
|
|
ctx.strokeStyle = 'rgba(120,200,255,0.5)';
|
|
ctx.lineWidth = 1;
|
|
ctx.beginPath();
|
|
ctx.arc(baseX, baseY, scale * 1.35, 0, TAU);
|
|
ctx.stroke();
|
|
ctx.beginPath();
|
|
ctx.moveTo(baseX - scale * 1.5, baseY);
|
|
ctx.lineTo(baseX - scale * 1.2, baseY);
|
|
ctx.moveTo(baseX + scale * 1.2, baseY);
|
|
ctx.lineTo(baseX + scale * 1.5, baseY);
|
|
ctx.stroke();
|
|
}
|
|
|
|
if (sky.paused) {
|
|
ctx.fillStyle = 'rgba(255,255,255,0.7)';
|
|
ctx.font = '600 13px "Segoe UI", sans-serif';
|
|
ctx.fillText('SKY FROZEN', 14, 24);
|
|
}
|
|
};
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Exhibit
|
|
* ------------------------------------------------------------------ */
|
|
|
|
function PlanetariumExhibit(options) {
|
|
this.canvas = options.canvas;
|
|
this.sky = new Sky();
|
|
this.renderer = new Renderer(this.canvas, this.sky);
|
|
this.announcer = options.announcer;
|
|
this.onChange = options.onChange || function () {};
|
|
this._lastFrame = 0;
|
|
this._running = false;
|
|
this._boundFrame = this._frame.bind(this);
|
|
}
|
|
|
|
PlanetariumExhibit.prototype.start = function () {
|
|
if (this._running) return;
|
|
this._running = true;
|
|
this._lastFrame = performance.now();
|
|
requestAnimationFrame(this._boundFrame);
|
|
};
|
|
|
|
PlanetariumExhibit.prototype._frame = function (now) {
|
|
if (!this._running) return;
|
|
var dt = Math.min(0.05, (now - this._lastFrame) / 1000);
|
|
this._lastFrame = now;
|
|
this.sky.step(dt);
|
|
this.renderer.draw();
|
|
requestAnimationFrame(this._boundFrame);
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.resize = function () { this.renderer.resize(); };
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Absolute, idempotent setters
|
|
* ------------------------------------------------------------------ */
|
|
|
|
PlanetariumExhibit.prototype.setConstellation = function (id) {
|
|
if (this.sky.constellation === id) return { changed: false };
|
|
this.sky.constellation = id;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setMagnitudeLimit = function (value) {
|
|
if (this.sky.magnitudeLimit === value) return { changed: false };
|
|
this.sky.magnitudeLimit = value;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setAzimuth = function (value) {
|
|
if (this.sky.azimuth === value) return { changed: false };
|
|
this.sky.azimuth = value;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setAltitude = function (value) {
|
|
if (this.sky.altitude === value) return { changed: false };
|
|
this.sky.altitude = value;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setTimeScale = function (value) {
|
|
if (this.sky.timeScale === value) return { changed: false };
|
|
this.sky.timeScale = value;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setFilter = function (id) {
|
|
if (this.sky.filter === id) return { changed: false };
|
|
this.sky.filter = id;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setTracking = function (on) {
|
|
if (this.sky.tracking === on) return { changed: false };
|
|
this.sky.tracking = on;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.setPaused = function (on) {
|
|
if (this.sky.paused === on) return { changed: false };
|
|
this.sky.paused = on;
|
|
this.onChange();
|
|
return { changed: true };
|
|
};
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Real actions
|
|
* ------------------------------------------------------------------ */
|
|
|
|
PlanetariumExhibit.prototype.advanceTime = function (args) {
|
|
var minutes = 10;
|
|
if (args && typeof args.minutes === 'number') {
|
|
if (!isFinite(args.minutes) || args.minutes < 1 || args.minutes > 240) {
|
|
return { ok: false, code: 'INVALID_ARGUMENTS', message: 'minutes must be between 1 and 240.' };
|
|
}
|
|
minutes = Math.round(args.minutes);
|
|
}
|
|
this.sky.skyTime += minutes / 60;
|
|
this.announcer.flash('Advanced sky time by ' + minutes + ' minutes.');
|
|
this.onChange();
|
|
return { ok: true, args: { minutes: minutes } };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.resetSky = function () {
|
|
this.sky.skyTime = 0;
|
|
this.announcer.flash('Sky time reset to epoch.');
|
|
this.onChange();
|
|
return { ok: true };
|
|
};
|
|
|
|
PlanetariumExhibit.prototype.toggleTracking = function () {
|
|
this.sky.tracking = !this.sky.tracking;
|
|
this.announcer.flash(this.sky.tracking ? 'Tracking engaged.' : 'Tracking disengaged.');
|
|
this.onChange();
|
|
return { ok: true };
|
|
};
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Reads
|
|
* ------------------------------------------------------------------ */
|
|
|
|
PlanetariumExhibit.prototype.read = function (targetId) {
|
|
var s = this.sky;
|
|
switch (targetId) {
|
|
case 'sky.constellation': return s.constellation;
|
|
case 'sky.magnitude-limit': return s.magnitudeLimit;
|
|
case 'sky.azimuth': return s.azimuth;
|
|
case 'sky.altitude': return s.altitude;
|
|
case 'sky.time-scale': return s.timeScale;
|
|
case 'sky.filter': return s.filter;
|
|
case 'sky.tracking': return s.tracking;
|
|
case 'sky.paused': return s.paused;
|
|
case 'telemetry.visible-stars': return this._visibleStarCount();
|
|
case 'telemetry.sky-time': return Math.round(s.skyTime * 100) / 100;
|
|
case 'telemetry.moon-phase': return Math.round(((s.skyTime * 0.09) % 1) * 100) / 100;
|
|
default: return null;
|
|
}
|
|
};
|
|
|
|
PlanetariumExhibit.prototype._visibleStarCount = function () {
|
|
var count = 0;
|
|
for (var i = 0; i < this.sky.stars.length; i++) {
|
|
if (this.sky.stars[i].mag <= this.sky.magnitudeLimit) count++;
|
|
}
|
|
return count;
|
|
};
|
|
|
|
/* ------------------------------------------------------------------ *
|
|
* Native UI
|
|
* ------------------------------------------------------------------ */
|
|
|
|
function PlanetariumUI(exhibit, announcer) {
|
|
this.exhibit = exhibit;
|
|
this.announcer = announcer;
|
|
this.nodes = {
|
|
constellation: document.getElementById('constellation-select'),
|
|
magnitude: document.getElementById('magnitude-range'),
|
|
magnitudeReadout: document.getElementById('magnitude-readout'),
|
|
azimuth: document.getElementById('azimuth-range'),
|
|
azimuthReadout: document.getElementById('azimuth-readout'),
|
|
altitude: document.getElementById('altitude-range'),
|
|
altitudeReadout: document.getElementById('altitude-readout'),
|
|
timeScale: document.getElementById('timescale-range'),
|
|
timeScaleReadout: document.getElementById('timescale-readout'),
|
|
filter: document.getElementById('filter-select'),
|
|
tracking: document.getElementById('tracking-button'),
|
|
pause: document.getElementById('pause-button'),
|
|
advance: document.getElementById('advance-button'),
|
|
reset: document.getElementById('reset-button')
|
|
};
|
|
this._buildOptions();
|
|
this._bind();
|
|
this.sync();
|
|
}
|
|
|
|
PlanetariumUI.prototype._buildOptions = function () {
|
|
var c = this.nodes.constellation;
|
|
for (var i = 0; i < CATALOG.length; i++) {
|
|
var opt = document.createElement('option');
|
|
opt.value = CATALOG[i].id;
|
|
opt.textContent = CATALOG[i].label;
|
|
c.appendChild(opt);
|
|
}
|
|
var f = this.nodes.filter;
|
|
for (var j = 0; j < FILTERS.length; j++) {
|
|
var fopt = document.createElement('option');
|
|
fopt.value = FILTERS[j].id;
|
|
fopt.textContent = FILTERS[j].label;
|
|
f.appendChild(fopt);
|
|
}
|
|
};
|
|
|
|
PlanetariumUI.prototype._bind = function () {
|
|
var self = this;
|
|
var ex = this.exhibit;
|
|
|
|
this.nodes.constellation.addEventListener('change', function (e) {
|
|
self.dispatch('sky.constellation', e.target.value);
|
|
});
|
|
this.nodes.magnitude.addEventListener('input', function (e) {
|
|
self.dispatch('sky.magnitude-limit', Number(e.target.value));
|
|
});
|
|
this.nodes.azimuth.addEventListener('input', function (e) {
|
|
self.dispatch('sky.azimuth', Number(e.target.value));
|
|
});
|
|
this.nodes.altitude.addEventListener('input', function (e) {
|
|
self.dispatch('sky.altitude', Number(e.target.value));
|
|
});
|
|
this.nodes.timeScale.addEventListener('input', function (e) {
|
|
self.dispatch('sky.time-scale', Number(e.target.value));
|
|
});
|
|
this.nodes.filter.addEventListener('change', function (e) {
|
|
self.dispatch('sky.filter', e.target.value);
|
|
});
|
|
this.nodes.tracking.addEventListener('click', function () {
|
|
self.dispatch('sky.tracking', !ex.sky.tracking);
|
|
});
|
|
this.nodes.pause.addEventListener('click', function () {
|
|
self.dispatch('sky.paused', !ex.sky.paused);
|
|
});
|
|
this.nodes.advance.addEventListener('click', function () {
|
|
self.invoke('action.advance-time', { minutes: 30 });
|
|
});
|
|
this.nodes.reset.addEventListener('click', function () {
|
|
self.invoke('action.reset-sky');
|
|
});
|
|
};
|
|
|
|
PlanetariumUI.prototype.dispatch = function (targetId, value) {
|
|
if (typeof this.dispatchOverride === 'function') {
|
|
this.dispatchOverride(targetId, value);
|
|
return;
|
|
}
|
|
this._fallbackSet(targetId, value);
|
|
};
|
|
|
|
PlanetariumUI.prototype.invoke = function (targetId, args) {
|
|
if (typeof this.invokeOverride === 'function') {
|
|
this.invokeOverride(targetId, args);
|
|
return;
|
|
}
|
|
this._fallbackInvoke(targetId, args);
|
|
};
|
|
|
|
PlanetariumUI.prototype._fallbackSet = function (targetId, value) {
|
|
var ex = this.exhibit;
|
|
switch (targetId) {
|
|
case 'sky.constellation': ex.setConstellation(value); break;
|
|
case 'sky.magnitude-limit': ex.setMagnitudeLimit(value); break;
|
|
case 'sky.azimuth': ex.setAzimuth(value); break;
|
|
case 'sky.altitude': ex.setAltitude(value); break;
|
|
case 'sky.time-scale': ex.setTimeScale(value); break;
|
|
case 'sky.filter': ex.setFilter(value); break;
|
|
case 'sky.tracking': ex.setTracking(value); break;
|
|
case 'sky.paused': ex.setPaused(value); break;
|
|
default: break;
|
|
}
|
|
this.sync();
|
|
};
|
|
|
|
PlanetariumUI.prototype._fallbackInvoke = function (targetId, args) {
|
|
var ex = this.exhibit;
|
|
if (targetId === 'action.advance-time') ex.advanceTime(args || {});
|
|
else if (targetId === 'action.reset-sky') ex.resetSky();
|
|
else if (targetId === 'action.toggle-tracking') ex.toggleTracking();
|
|
this.sync();
|
|
};
|
|
|
|
PlanetariumUI.prototype.sync = function () {
|
|
var s = this.exhibit.sky;
|
|
var n = this.nodes;
|
|
var Shell = window.XZBTShell;
|
|
|
|
if (n.constellation.value !== s.constellation) n.constellation.value = s.constellation;
|
|
if (Number(n.magnitude.value) !== s.magnitudeLimit) n.magnitude.value = String(s.magnitudeLimit);
|
|
if (Number(n.azimuth.value) !== s.azimuth) n.azimuth.value = String(s.azimuth);
|
|
if (Number(n.altitude.value) !== s.altitude) n.altitude.value = String(s.altitude);
|
|
if (Number(n.timeScale.value) !== s.timeScale) n.timeScale.value = String(s.timeScale);
|
|
if (n.filter.value !== s.filter) n.filter.value = s.filter;
|
|
|
|
n.magnitudeReadout.textContent = 'mag \u2264 ' + Shell.formatNumber(s.magnitudeLimit, 1);
|
|
n.azimuthReadout.textContent = Shell.formatDegrees(s.azimuth);
|
|
n.altitudeReadout.textContent = Shell.formatDegrees(s.altitude);
|
|
n.timeScaleReadout.textContent = Shell.formatNumber(s.timeScale, 2) + '\u00d7';
|
|
n.tracking.setAttribute('aria-pressed', s.tracking ? 'true' : 'false');
|
|
n.pause.setAttribute('aria-pressed', s.paused ? 'true' : 'false');
|
|
n.pause.textContent = s.paused ? 'Resume sky' : 'Freeze sky';
|
|
};
|
|
|
|
window.PlanetariumExhibit = PlanetariumExhibit;
|
|
window.PlanetariumUI = PlanetariumUI;
|
|
window.PlanetariumData = { CATALOG: CATALOG, BODIES: BODIES, FILTERS: FILTERS };
|
|
})();
|