mirror of
https://github.com/Kpa-clawbot/meshcore-analyzer.git
synced 2026-03-30 15:55:49 +00:00
Revert "Matrix: CSS transition pooled markers for smoother animation"
This reverts commit 68d2fba54e.
This commit is contained in:
@@ -22,7 +22,7 @@
|
||||
<meta name="twitter:title" content="MeshCore Analyzer">
|
||||
<meta name="twitter:description" content="Real-time MeshCore LoRa mesh network analyzer — live packet visualization, node tracking, channel decryption, and route analysis.">
|
||||
<meta name="twitter:image" content="https://raw.githubusercontent.com/Kpa-clawbot/meshcore-analyzer/master/public/og-image.png">
|
||||
<link rel="stylesheet" href="style.css?v=1774164879">
|
||||
<link rel="stylesheet" href="style.css?v=1774164970">
|
||||
<link rel="stylesheet" href="home.css">
|
||||
<link rel="stylesheet" href="live.css?v=1774058575">
|
||||
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"
|
||||
@@ -90,7 +90,7 @@
|
||||
<script src="nodes.js?v=1774126708" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="traces.js?v=1774135052" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="analytics.js?v=1774126708" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="live.js?v=1774164879" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="live.js?v=1774164970" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observers.js?v=1774290000" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="observer-detail.js?v=1774028201" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
<script src="node-analytics.js?v=1774126708" onerror="console.error('Failed to load:', this.src)"></script>
|
||||
|
||||
127
public/live.js
127
public/live.js
@@ -1755,105 +1755,80 @@
|
||||
}
|
||||
|
||||
const matrixGreen = '#00ff41';
|
||||
const TRAIL_LEN = 6;
|
||||
const DURATION_MS = 1400;
|
||||
const SPAWN_EVERY_MS = DURATION_MS / 16; // ~87ms between chars
|
||||
const TRAIL_LEN = Math.min(6, bytes.length);
|
||||
const DURATION_MS = 1400; // total hop duration
|
||||
const CHAR_INTERVAL = 0.06; // spawn a char every 6% of progress
|
||||
const charMarkers = [];
|
||||
let nextCharAt = CHAR_INTERVAL;
|
||||
let byteIdx = 0;
|
||||
|
||||
const trail = L.polyline([from], {
|
||||
color: matrixGreen, weight: 1.5, opacity: 0.2, lineCap: 'round'
|
||||
}).addTo(pathsLayer);
|
||||
|
||||
// Pre-create reusable char markers with CSS transitions
|
||||
const pool = [];
|
||||
for (let i = 0; i < TRAIL_LEN; i++) {
|
||||
const m = L.marker(from, {
|
||||
icon: L.divIcon({
|
||||
className: 'matrix-char matrix-char-anim',
|
||||
html: `<span>${bytes[i % bytes.length]}</span>`,
|
||||
iconSize: [24, 18],
|
||||
iconAnchor: [12, 9]
|
||||
}),
|
||||
interactive: false
|
||||
});
|
||||
pool.push({ marker: m, active: false, spawnedAt: 0 });
|
||||
}
|
||||
|
||||
let poolIdx = 0;
|
||||
let byteIdx = 0;
|
||||
const trailCoords = [from];
|
||||
const startTime = performance.now();
|
||||
let lastSpawn = -Infinity;
|
||||
let trailCoords = [from];
|
||||
|
||||
function tick(now) {
|
||||
const elapsed = now - startTime;
|
||||
const t = Math.min(1, elapsed / DURATION_MS);
|
||||
const lat = from[0] + (to[0] - from[0]) * t;
|
||||
const lon = from[1] + (to[1] - from[1]) * t;
|
||||
trailCoords.push([lat, lon]);
|
||||
trail.setLatLngs(trailCoords);
|
||||
|
||||
// Update trail polyline less often (every ~3 frames)
|
||||
if (trailCoords.length === 0 || t >= 1 || elapsed - (trailCoords.length * (DURATION_MS / 30)) >= 0) {
|
||||
trailCoords.push([lat, lon]);
|
||||
trail.setLatLngs(trailCoords);
|
||||
// Remove old chars beyond trail length
|
||||
while (charMarkers.length > TRAIL_LEN) {
|
||||
const old = charMarkers.shift();
|
||||
try { animLayer.removeLayer(old.marker); } catch {}
|
||||
}
|
||||
|
||||
// Fade existing chars
|
||||
for (let i = 0; i < charMarkers.length; i++) {
|
||||
const age = charMarkers.length - i;
|
||||
const op = Math.max(0.15, 1 - (age / TRAIL_LEN) * 0.7);
|
||||
const size = Math.max(10, 16 - age * 1.5);
|
||||
const el = charMarkers[i].marker.getElement();
|
||||
if (el) { el.style.opacity = op; el.style.fontSize = size + 'px'; }
|
||||
}
|
||||
|
||||
// Spawn new char at intervals
|
||||
if (elapsed - lastSpawn >= SPAWN_EVERY_MS && t < 0.95) {
|
||||
lastSpawn = elapsed;
|
||||
const slot = pool[poolIdx % TRAIL_LEN];
|
||||
|
||||
// Recycle: remove old, update text
|
||||
if (slot.active) {
|
||||
// Just update position — CSS transition handles smoothness
|
||||
} else {
|
||||
slot.marker.addTo(animLayer);
|
||||
slot.active = true;
|
||||
// Apply CSS transition after first paint
|
||||
requestAnimationFrame(() => {
|
||||
const el = slot.marker.getElement();
|
||||
if (el) el.style.transition = 'transform 80ms linear, opacity 200ms ease';
|
||||
});
|
||||
}
|
||||
|
||||
// Update byte text
|
||||
const el = slot.marker.getElement();
|
||||
if (el) {
|
||||
const span = el.querySelector('span');
|
||||
if (span) span.textContent = bytes[byteIdx % bytes.length];
|
||||
el.style.opacity = '1';
|
||||
el.style.fontSize = '16px';
|
||||
}
|
||||
slot.marker.setLatLng([lat, lon]);
|
||||
slot.spawnedAt = elapsed;
|
||||
if (t >= nextCharAt && t < 1) {
|
||||
nextCharAt += CHAR_INTERVAL;
|
||||
const charEl = L.marker([lat, lon], {
|
||||
icon: L.divIcon({
|
||||
className: 'matrix-char',
|
||||
html: `<span style="color:#fff;font-family:'Courier New',monospace;font-size:16px;font-weight:bold;text-shadow:0 0 8px ${matrixGreen},0 0 16px ${matrixGreen},0 0 24px ${matrixGreen}60;pointer-events:none">${bytes[byteIdx % bytes.length]}</span>`,
|
||||
iconSize: [24, 18],
|
||||
iconAnchor: [12, 9]
|
||||
}),
|
||||
interactive: false
|
||||
}).addTo(animLayer);
|
||||
charMarkers.push({ marker: charEl });
|
||||
byteIdx++;
|
||||
poolIdx++;
|
||||
|
||||
// Fade older chars
|
||||
for (let i = 0; i < pool.length; i++) {
|
||||
if (!pool[i].active) continue;
|
||||
const age = elapsed - pool[i].spawnedAt;
|
||||
if (age > SPAWN_EVERY_MS * 0.5) {
|
||||
const fadeT = Math.min(1, age / (SPAWN_EVERY_MS * TRAIL_LEN));
|
||||
const op = Math.max(0.1, 1 - fadeT * 0.85);
|
||||
const sz = Math.max(10, 16 - fadeT * 6);
|
||||
const pel = pool[i].marker.getElement();
|
||||
if (pel) { pel.style.opacity = op; pel.style.fontSize = sz + 'px'; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (t < 1) {
|
||||
requestAnimationFrame(tick);
|
||||
} else {
|
||||
// Fade out everything
|
||||
for (const slot of pool) {
|
||||
const el = slot.marker.getElement();
|
||||
if (el) { el.style.transition = 'opacity 500ms ease'; el.style.opacity = '0'; }
|
||||
// Fade out
|
||||
const fadeStart = performance.now();
|
||||
function fadeOut(now) {
|
||||
const ft = Math.min(1, (now - fadeStart) / 500);
|
||||
if (ft >= 1) {
|
||||
for (const cm of charMarkers) try { animLayer.removeLayer(cm.marker); } catch {}
|
||||
try { pathsLayer.removeLayer(trail); } catch {}
|
||||
charMarkers.length = 0;
|
||||
} else {
|
||||
const op = 1 - ft;
|
||||
for (const cm of charMarkers) {
|
||||
const el = cm.marker.getElement(); if (el) el.style.opacity = op * 0.5;
|
||||
}
|
||||
trail.setStyle({ opacity: op * 0.15 });
|
||||
requestAnimationFrame(fadeOut);
|
||||
}
|
||||
}
|
||||
trail.setStyle({ opacity: 0.05 });
|
||||
setTimeout(() => {
|
||||
for (const slot of pool) { try { animLayer.removeLayer(slot.marker); } catch {} }
|
||||
try { pathsLayer.removeLayer(trail); } catch {}
|
||||
}, 600);
|
||||
setTimeout(() => requestAnimationFrame(fadeOut), 300);
|
||||
if (onComplete) onComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1533,13 +1533,7 @@ tr[data-hops]:hover { background: rgba(59,130,246,0.1); }
|
||||
|
||||
/* Matrix mode hex animation */
|
||||
.matrix-char { background: none !important; border: none !important; }
|
||||
.matrix-char span {
|
||||
display: block; text-align: center; white-space: nowrap; line-height: 1;
|
||||
color: #fff; font-family: 'Courier New', monospace; font-size: 16px; font-weight: bold;
|
||||
text-shadow: 0 0 8px #00ff41, 0 0 16px #00ff41, 0 0 24px #00ff4160;
|
||||
pointer-events: none;
|
||||
}
|
||||
.matrix-char-anim { transition: transform 80ms linear, opacity 200ms ease; will-change: transform, opacity; }
|
||||
.matrix-char span { display: block; text-align: center; white-space: nowrap; line-height: 1; }
|
||||
|
||||
/* === Matrix Theme === */
|
||||
.matrix-theme .leaflet-tile-pane {
|
||||
|
||||
Reference in New Issue
Block a user