Ladebalken bei Layer-Aktivierung + Ortsnamen-Rendering verbessert
- Animierter Ladebalken unter jedem Layer-Toggle bei Datenabruf - Status-Text (Lade Daten.../Fehler beim Laden) - Fetch-Wrapper: nur 401 redirected zum Login, nicht 403 - Ortsnamen: minimumLevel, tileWidth/Height, LINEAR Texture-Filter fuer konsistente Schriftgroessen beim Laden
Dieser Commit ist enthalten in:
@@ -112,3 +112,40 @@ html, body { height: 100%; overflow: hidden; background: var(--bg-primary); colo
|
||||
.cesium-selection-wrapper {
|
||||
border-color: var(--accent) !important;
|
||||
}
|
||||
|
||||
|
||||
/* === Loading Indicator === */
|
||||
.layer-loading {
|
||||
display: none;
|
||||
height: 2px;
|
||||
background: var(--accent);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
border-radius: 1px;
|
||||
margin: 4px 0 0;
|
||||
}
|
||||
.layer-loading.active {
|
||||
display: block;
|
||||
}
|
||||
.layer-loading::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -40%;
|
||||
width: 40%;
|
||||
height: 100%;
|
||||
background: linear-gradient(90deg, transparent, #00ff88, transparent);
|
||||
animation: layer-loading-slide 1s ease-in-out infinite;
|
||||
}
|
||||
@keyframes layer-loading-slide {
|
||||
0% { left: -40%; }
|
||||
100% { left: 100%; }
|
||||
}
|
||||
.layer-status {
|
||||
font-size: 9px;
|
||||
color: var(--text-dim);
|
||||
margin-top: 2px;
|
||||
display: none;
|
||||
}
|
||||
.layer-status.active {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
opts.headers['Authorization'] = 'Bearer ' + localStorage.getItem('globe_token');
|
||||
}
|
||||
return _origFetch(url, opts).then(function(r) {
|
||||
if (r.status === 401 || r.status === 403) { localStorage.removeItem('globe_token'); window.location.href = '/login'; }
|
||||
if (r.status === 401) { localStorage.removeItem('globe_token'); window.location.href = '/login'; }
|
||||
return r;
|
||||
});
|
||||
};
|
||||
@@ -52,24 +52,32 @@
|
||||
<span class="layer-name">Flugverkehr</span>
|
||||
<span class="layer-count" id="count-flights">-</span>
|
||||
</label>
|
||||
<div class="layer-loading" id="loading-flights"></div>
|
||||
<div class="layer-status" id="status-flights"></div>
|
||||
<label class="layer-toggle">
|
||||
<input type="checkbox" id="layer-ships" checked>
|
||||
<span class="layer-dot dot-ships"></span>
|
||||
<span class="layer-name">Schiffsverkehr</span>
|
||||
<span class="layer-count" id="count-ships">-</span>
|
||||
</label>
|
||||
<div class="layer-loading" id="loading-ships"></div>
|
||||
<div class="layer-status" id="status-ships"></div>
|
||||
<label class="layer-toggle">
|
||||
<input type="checkbox" id="layer-quakes">
|
||||
<span class="layer-dot dot-quakes"></span>
|
||||
<span class="layer-name">Erdbeben</span>
|
||||
<span class="layer-count" id="count-quakes">-</span>
|
||||
</label>
|
||||
<div class="layer-loading" id="loading-quakes"></div>
|
||||
<div class="layer-status" id="status-quakes"></div>
|
||||
<label class="layer-toggle">
|
||||
<input type="checkbox" id="layer-gdelt">
|
||||
<span class="layer-dot dot-gdelt"></span>
|
||||
<span class="layer-name">Nachrichten</span>
|
||||
<span class="layer-count" id="count-gdelt">-</span>
|
||||
</label>
|
||||
<div class="layer-loading" id="loading-gdelt"></div>
|
||||
<div class="layer-status" id="status-gdelt"></div>
|
||||
</div>
|
||||
<div class="panel-divider"></div>
|
||||
<div class="panel-section">
|
||||
|
||||
@@ -89,11 +89,16 @@ const Globe = {
|
||||
this._labelsLayer = this.viewer.imageryLayers.addImageryProvider(
|
||||
new Cesium.UrlTemplateImageryProvider({
|
||||
url: 'https://server.arcgisonline.com/ArcGIS/rest/services/Reference/World_Boundaries_and_Places/MapServer/tile/{z}/{y}/{x}',
|
||||
minimumLevel: 1,
|
||||
maximumLevel: 18,
|
||||
tileWidth: 256,
|
||||
tileHeight: 256,
|
||||
credit: 'Esri',
|
||||
})
|
||||
);
|
||||
this._labelsLayer.alpha = 0.9;
|
||||
this._labelsLayer.alpha = 0.95;
|
||||
this._labelsLayer.minificationFilter = Cesium.TextureMinificationFilter.LINEAR;
|
||||
this._labelsLayer.magnificationFilter = Cesium.TextureMagnificationFilter.LINEAR;
|
||||
} else if (!on && this._labelsLayer) {
|
||||
this.viewer.imageryLayers.remove(this._labelsLayer);
|
||||
this._labelsLayer = null;
|
||||
|
||||
@@ -28,6 +28,10 @@ const FlightsLayer = {
|
||||
|
||||
_fetch() {
|
||||
var self = this;
|
||||
var loadEl = document.getElementById('loading-flights');
|
||||
var statusEl = document.getElementById('status-flights');
|
||||
if (loadEl) loadEl.classList.add('active');
|
||||
if (statusEl) { statusEl.textContent = 'Lade Daten...'; statusEl.classList.add('active'); }
|
||||
fetch('/api/flights')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
@@ -72,6 +76,7 @@ const FlightsLayer = {
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function(e) { console.warn('Flights fetch error:', e); });
|
||||
.catch(function(e) { console.warn('Flights fetch error:', e); if (statusEl) { statusEl.textContent = 'Fehler beim Laden'; } })
|
||||
.finally(function() { if (loadEl) loadEl.classList.remove('active'); setTimeout(function() { if (statusEl) statusEl.classList.remove('active'); }, 3000); });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -28,6 +28,10 @@ const GdeltLayer = {
|
||||
|
||||
_fetch() {
|
||||
var self = this;
|
||||
var loadEl = document.getElementById('loading-gdelt');
|
||||
var statusEl = document.getElementById('status-gdelt');
|
||||
if (loadEl) loadEl.classList.add('active');
|
||||
if (statusEl) { statusEl.textContent = 'Lade Daten...'; statusEl.classList.add('active'); }
|
||||
fetch('/api/gdelt')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
|
||||
@@ -28,6 +28,10 @@ const QuakesLayer = {
|
||||
|
||||
_fetch() {
|
||||
var self = this;
|
||||
var loadEl = document.getElementById('loading-quakes');
|
||||
var statusEl = document.getElementById('status-quakes');
|
||||
if (loadEl) loadEl.classList.add('active');
|
||||
if (statusEl) { statusEl.textContent = 'Lade Daten...'; statusEl.classList.add('active'); }
|
||||
fetch('/api/quakes')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
@@ -66,6 +70,7 @@ const QuakesLayer = {
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function(e) { console.warn('Quakes fetch error:', e); });
|
||||
.catch(function(e) { console.warn('Quakes fetch error:', e); if (statusEl) { statusEl.textContent = 'Fehler beim Laden'; } })
|
||||
.finally(function() { if (loadEl) loadEl.classList.remove('active'); setTimeout(function() { if (statusEl) statusEl.classList.remove('active'); }, 3000); });
|
||||
},
|
||||
};
|
||||
|
||||
@@ -28,6 +28,10 @@ const ShipsLayer = {
|
||||
|
||||
_fetch() {
|
||||
var self = this;
|
||||
var loadEl = document.getElementById('loading-ships');
|
||||
var statusEl = document.getElementById('status-ships');
|
||||
if (loadEl) loadEl.classList.add('active');
|
||||
if (statusEl) { statusEl.textContent = 'Lade Daten...'; statusEl.classList.add('active'); }
|
||||
fetch('/api/ships')
|
||||
.then(function(r) { return r.json(); })
|
||||
.then(function(data) {
|
||||
@@ -72,6 +76,7 @@ const ShipsLayer = {
|
||||
});
|
||||
});
|
||||
})
|
||||
.catch(function(e) { console.warn('Ships fetch error:', e); });
|
||||
.catch(function(e) { console.warn('Ships fetch error:', e); if (statusEl) { statusEl.textContent = 'Fehler beim Laden'; } })
|
||||
.finally(function() { if (loadEl) loadEl.classList.remove('active'); setTimeout(function() { if (statusEl) statusEl.classList.remove('active'); }, 3000); });
|
||||
},
|
||||
};
|
||||
|
||||
In neuem Issue referenzieren
Einen Benutzer sperren