промежуточная работа
This commit is contained in:
@@ -196,3 +196,78 @@ h1 {
|
||||
font-size: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.accordion-header {
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.accordion-header:hover {
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.accordion-body {
|
||||
max-height: 520px;
|
||||
overflow: hidden;
|
||||
transition: max-height 0.3s ease;
|
||||
}
|
||||
|
||||
.accordion-body.collapsed {
|
||||
max-height: 0;
|
||||
}
|
||||
|
||||
.progress-with-signal {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0;
|
||||
}
|
||||
|
||||
.progress-90 {
|
||||
flex: 0 0 86%;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
/* ===== SIGNAL ICON ===== */
|
||||
.signal-icon {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 4px;
|
||||
width: 34px;
|
||||
height: 34px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.sig-bar {
|
||||
flex: 1;
|
||||
border-radius: 2px;
|
||||
min-width: 5px;
|
||||
border: 1.5px solid #00ff88;
|
||||
background-color: transparent;
|
||||
transition: background-color 0.3s, border-color 0.3s;
|
||||
}
|
||||
|
||||
.sig-bar-1 { height: 25%; }
|
||||
.sig-bar-2 { height: 50%; }
|
||||
.sig-bar-3 { height: 75%; }
|
||||
.sig-bar-4 { height: 100%; }
|
||||
|
||||
/* Активные — зелёная заливка */
|
||||
.sig-bar.active-1,
|
||||
.sig-bar.active-2,
|
||||
.sig-bar.active-3,
|
||||
.sig-bar.active-4 {
|
||||
background-color: #00ff88;
|
||||
border-color: #00ff88;
|
||||
}
|
||||
|
||||
/* Неактивные — прозрачные, только контур */
|
||||
.sig-bar.dim {
|
||||
background-color: transparent;
|
||||
border-color: #1a3a1a;
|
||||
}
|
||||
|
||||
#last-byte {
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
color: #00ff88;
|
||||
}
|
||||
@@ -21,19 +21,21 @@
|
||||
<div id="meta"></div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<h3>ПОСЛЕДНИЙ СИГНАЛ</h3>
|
||||
<div id="latest">--</div>
|
||||
<div id="bits"></div>
|
||||
</div>
|
||||
|
||||
<div class="card wide">
|
||||
<h3>УРОВНИ КАНАЛОВ</h3>
|
||||
|
||||
<div class="progress-row">
|
||||
<div class="progress-label">Канал 1</div>
|
||||
<div class="progress">
|
||||
<div class="fill" id="bar1"></div>
|
||||
<div class="progress-label">Канал 1 — <span id="last-byte">0</span></div>
|
||||
<div class="progress-with-signal">
|
||||
<div class="progress progress-90">
|
||||
<div class="fill" id="bar1"></div>
|
||||
</div>
|
||||
<div class="signal-icon" id="signal-icon" aria-label="Уровень сигнала" role="img">
|
||||
<div class="sig-bar sig-bar-1"></div>
|
||||
<div class="sig-bar sig-bar-2"></div>
|
||||
<div class="sig-bar sig-bar-3"></div>
|
||||
<div class="sig-bar sig-bar-4"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -53,8 +55,10 @@
|
||||
</div>
|
||||
|
||||
<div class="card wide">
|
||||
<h3>ПОТОК ДАННЫХ (последние 32)</h3>
|
||||
<div id="history"></div>
|
||||
<h3 class="accordion-header" id="history-header">▶ ПРИНЯТЫЕ ДАННЫЕ</h3>
|
||||
<div class="accordion-body" id="history-body">
|
||||
<div id="history"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,19 +1,14 @@
|
||||
// ===== BIT RENDER =====
|
||||
function renderBits(byte) {
|
||||
const bits = document.getElementById("bits");
|
||||
bits.innerHTML = "";
|
||||
// ===== ACCORDION =====
|
||||
const historyHeader = document.getElementById("history-header");
|
||||
const historyBody = document.getElementById("history-body");
|
||||
let accordionOpen = false;
|
||||
historyBody.classList.add("collapsed"); // изначально свёрнут
|
||||
|
||||
byte = Number(byte || 0);
|
||||
|
||||
for (let i = 7; i >= 0; i--) {
|
||||
const v = (byte >> i) & 1;
|
||||
|
||||
const d = document.createElement("div");
|
||||
d.className = "bit" + (v ? " on" : "");
|
||||
d.textContent = v;
|
||||
bits.appendChild(d);
|
||||
}
|
||||
}
|
||||
historyHeader.addEventListener("click", () => {
|
||||
accordionOpen = !accordionOpen;
|
||||
historyHeader.textContent = (accordionOpen ? "▼" : "▶") + " ПРИНЯТЫЕ ДАННЫЕ";
|
||||
historyBody.classList.toggle("collapsed", !accordionOpen);
|
||||
});
|
||||
|
||||
// ===== PROGRESS BAR =====
|
||||
function setBar(id, value) {
|
||||
@@ -21,6 +16,31 @@ function setBar(id, value) {
|
||||
document.getElementById(id).style.width = value + "%";
|
||||
}
|
||||
|
||||
// ===== SIGNAL ICON =====
|
||||
function setSignal(percent) {
|
||||
const bars = document.querySelectorAll(".sig-bar");
|
||||
bars.forEach(b => {
|
||||
b.classList.remove("active-1", "active-2", "active-3", "active-4");
|
||||
b.classList.add("dim");
|
||||
});
|
||||
|
||||
if (percent > 75) {
|
||||
bars[0].classList.add("active-1"); bars[0].classList.remove("dim");
|
||||
bars[1].classList.add("active-2"); bars[1].classList.remove("dim");
|
||||
bars[2].classList.add("active-3"); bars[2].classList.remove("dim");
|
||||
bars[3].classList.add("active-4"); bars[3].classList.remove("dim");
|
||||
} else if (percent > 50) {
|
||||
bars[0].classList.add("active-1"); bars[0].classList.remove("dim");
|
||||
bars[1].classList.add("active-2"); bars[1].classList.remove("dim");
|
||||
bars[2].classList.add("active-3"); bars[2].classList.remove("dim");
|
||||
} else if (percent > 25) {
|
||||
bars[0].classList.add("active-1"); bars[0].classList.remove("dim");
|
||||
bars[1].classList.add("active-2"); bars[1].classList.remove("dim");
|
||||
} else if (percent > 0) {
|
||||
bars[0].classList.add("active-1"); bars[0].classList.remove("dim");
|
||||
}
|
||||
}
|
||||
|
||||
// ===== SMOOTHING =====
|
||||
let lastValue = 0;
|
||||
|
||||
@@ -60,12 +80,6 @@ async function update() {
|
||||
document.getElementById("meta").textContent =
|
||||
"аптайм: " + uptime + "s | буфер: " + filled;
|
||||
|
||||
// ===== LATEST =====
|
||||
const latest = Number(h.latest || 0);
|
||||
document.getElementById("latest").textContent = latest;
|
||||
|
||||
renderBits(latest);
|
||||
|
||||
// ===== HISTORY =====
|
||||
const arr = Array.isArray(hist.bytes) ? hist.bytes : [];
|
||||
|
||||
@@ -89,6 +103,8 @@ async function update() {
|
||||
|
||||
// ===== ONLY CHANNEL 1 =====
|
||||
setBar("bar1", smooth);
|
||||
document.getElementById("last-byte").textContent = filtered;
|
||||
setSignal(smooth);
|
||||
|
||||
} catch (e) {
|
||||
console.error("UPDATE ERROR:", e);
|
||||
@@ -96,6 +112,5 @@ async function update() {
|
||||
}
|
||||
}
|
||||
|
||||
// быстрее и плавнее
|
||||
setInterval(update, 500);
|
||||
update();
|
||||
update();
|
||||
Reference in New Issue
Block a user