Züge fahren flüssig statt zu springen
Server liefert zusätzlich die Position in 10 s, der Browser interpoliert dazwischen (~15 fps). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X48pE4bzjHej8w9HyZXCjb
This commit is contained in:
+32
-2
@@ -88,14 +88,44 @@ document.getElementById("btn-sat").onclick = () => setBackground(true);
|
||||
|
||||
// ---------- Züge ----------
|
||||
|
||||
// Server liefert je Zug die Position jetzt und in `ahead` Sekunden; dazwischen wird linear gefahren.
|
||||
let trains = { type: "FeatureCollection", features: [] };
|
||||
let ts = 0, ahead = 10, clockOffset = 0;
|
||||
|
||||
async function refreshTrains() {
|
||||
if (document.hidden) return;
|
||||
try {
|
||||
const r = await fetch("api/vehicles");
|
||||
if (r.ok) map.getSource("trains").setData(await r.json());
|
||||
if (!r.ok) return;
|
||||
const now = Number(r.headers.get("X-Now"));
|
||||
const d = await r.json();
|
||||
if (now) clockOffset = Date.now() / 1000 - now;
|
||||
for (const f of d.features) f.start = f.geometry.coordinates;
|
||||
trains = d;
|
||||
ts = d.ts;
|
||||
ahead = d.ahead || 10;
|
||||
} catch (e) { /* nächster Versuch in ein paar Sekunden */ }
|
||||
}
|
||||
|
||||
function render() {
|
||||
// leicht über `ahead` hinaus weiterfahren, falls eine Abfrage hängt, dann anhalten
|
||||
const k = Math.max(0, Math.min((Date.now() / 1000 - clockOffset - ts) / ahead, 1.5));
|
||||
for (const f of trains.features) {
|
||||
if (!f.next) continue;
|
||||
f.geometry.coordinates = [f.start[0] + (f.next[0] - f.start[0]) * k, f.start[1] + (f.next[1] - f.start[1]) * k];
|
||||
}
|
||||
map.getSource("trains").setData(trains);
|
||||
}
|
||||
|
||||
let lastFrame = 0;
|
||||
function animate(ms) {
|
||||
if (!document.hidden && ms - lastFrame > 66) { // ~15 Bilder/s reichen und schonen Akku
|
||||
lastFrame = ms;
|
||||
render();
|
||||
}
|
||||
requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
async function refreshStatus() {
|
||||
const el = document.getElementById("status");
|
||||
try {
|
||||
@@ -173,8 +203,8 @@ map.on("load", () => {
|
||||
setBackground(sat);
|
||||
refreshTrains();
|
||||
refreshStatus();
|
||||
// shortcut: Züge springen alle 5 s; für flüssige Bewegung clientseitig interpolieren
|
||||
setInterval(refreshTrains, 5000);
|
||||
requestAnimationFrame(animate);
|
||||
setInterval(refreshStatus, 30000);
|
||||
setInterval(() => openId && showTrip(openId), 30000);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user