mirror of
https://github.com/wwiinnddyy/LanMountainDesktop.git
synced 2026-06-20 23:54:26 +08:00
899 lines
31 KiB
HTML
899 lines
31 KiB
HTML
|
|
<!DOCTYPE html>
|
|||
|
|
<html lang="zh-CN">
|
|||
|
|
<head>
|
|||
|
|
<meta charset="UTF-8">
|
|||
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|||
|
|
<title>噪音等级组件改造 Mockup v2</title>
|
|||
|
|
<style>
|
|||
|
|
@import url('https://fonts.googleapis.com/css2?family=Noto+Sans+SC:wght@300;400;500;600;700&display=swap');
|
|||
|
|
|
|||
|
|
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|||
|
|
|
|||
|
|
:root {
|
|||
|
|
--quiet: #34D399;
|
|||
|
|
--normal: #60A5FA;
|
|||
|
|
--noisy: #F59E0B;
|
|||
|
|
--extreme: #EF4444;
|
|||
|
|
--bg: #0B1220;
|
|||
|
|
--surface: #131D2E;
|
|||
|
|
--surface-raised: #182438;
|
|||
|
|
--border: rgba(255,255,255,0.08);
|
|||
|
|
--text-primary: #EFF3FF;
|
|||
|
|
--text-secondary: #8B9BB8;
|
|||
|
|
--text-muted: #5C6D86;
|
|||
|
|
--radius-component: 24px;
|
|||
|
|
--radius-xs: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
body {
|
|||
|
|
font-family: 'Noto Sans SC', -apple-system, sans-serif;
|
|||
|
|
background: var(--bg);
|
|||
|
|
color: var(--text-primary);
|
|||
|
|
min-height: 100vh;
|
|||
|
|
padding: 40px 20px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.page-header {
|
|||
|
|
text-align: center;
|
|||
|
|
margin-bottom: 48px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.page-header h1 {
|
|||
|
|
font-size: 28px;
|
|||
|
|
font-weight: 700;
|
|||
|
|
letter-spacing: -0.5px;
|
|||
|
|
margin-bottom: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.page-header p {
|
|||
|
|
font-size: 14px;
|
|||
|
|
color: var(--text-secondary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.section {
|
|||
|
|
max-width: 1200px;
|
|||
|
|
margin: 0 auto 56px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.section-title {
|
|||
|
|
font-size: 18px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin-bottom: 6px;
|
|||
|
|
color: var(--text-primary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.section-desc {
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: var(--text-secondary);
|
|||
|
|
margin-bottom: 24px;
|
|||
|
|
line-height: 1.6;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.mockup-row {
|
|||
|
|
display: grid;
|
|||
|
|
grid-template-columns: repeat(auto-fit, minmax(340px, 1fr));
|
|||
|
|
gap: 24px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.widget-card {
|
|||
|
|
background: var(--surface-raised);
|
|||
|
|
border: 1px solid var(--border);
|
|||
|
|
border-radius: var(--radius-component);
|
|||
|
|
padding: 16px 14px;
|
|||
|
|
position: relative;
|
|||
|
|
overflow: hidden;
|
|||
|
|
animation: fadeIn 0.5s ease both;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.widget-card:nth-child(2) { animation-delay: 0.08s; }
|
|||
|
|
|
|||
|
|
.widget-label {
|
|||
|
|
position: absolute;
|
|||
|
|
top: -1px;
|
|||
|
|
right: 20px;
|
|||
|
|
background: rgba(96, 165, 250, 0.2);
|
|||
|
|
border: 1px solid rgba(96, 165, 250, 0.3);
|
|||
|
|
border-top: none;
|
|||
|
|
border-radius: 0 0 8px 8px;
|
|||
|
|
padding: 3px 10px;
|
|||
|
|
font-size: 11px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #8BE8FF;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@keyframes fadeIn {
|
|||
|
|
from { opacity: 0; transform: translateY(8px); }
|
|||
|
|
to { opacity: 1; transform: translateY(0); }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ====== 通用组件样式 ====== */
|
|||
|
|
.chart-header {
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
margin-bottom: 12px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.chart-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: var(--text-secondary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.chart-badge {
|
|||
|
|
padding: 3px 8px;
|
|||
|
|
border-radius: var(--radius-xs);
|
|||
|
|
border: 1px solid rgba(255,255,255,0.3);
|
|||
|
|
font-size: 12px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
color: #fff;
|
|||
|
|
transition: background 0.4s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.chart-area {
|
|||
|
|
position: relative;
|
|||
|
|
height: 170px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.y-axis {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 0;
|
|||
|
|
top: 0;
|
|||
|
|
bottom: 22px;
|
|||
|
|
width: 52px;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
padding: 4px 0;
|
|||
|
|
z-index: 3;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.y-label {
|
|||
|
|
font-size: 10px;
|
|||
|
|
padding-left: 2px;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
transition: color 0.4s ease, font-weight 0.3s ease, opacity 0.4s ease;
|
|||
|
|
opacity: 0.45;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.y-label.active {
|
|||
|
|
font-weight: 600;
|
|||
|
|
opacity: 1;
|
|||
|
|
}
|
|||
|
|
.y-label.active.l-quiet { color: var(--quiet); }
|
|||
|
|
.y-label.active.l-normal { color: var(--normal); }
|
|||
|
|
.y-label.active.l-noisy { color: var(--noisy); }
|
|||
|
|
.y-label.active.l-extreme { color: var(--extreme); }
|
|||
|
|
|
|||
|
|
.curve-area {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 56px;
|
|||
|
|
right: 0;
|
|||
|
|
top: 0;
|
|||
|
|
bottom: 22px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.curve-area svg { width: 100%; height: 100%; }
|
|||
|
|
|
|||
|
|
.x-axis {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 56px;
|
|||
|
|
right: 0;
|
|||
|
|
bottom: 0;
|
|||
|
|
height: 22px;
|
|||
|
|
display: flex;
|
|||
|
|
justify-content: space-between;
|
|||
|
|
align-items: center;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.x-label {
|
|||
|
|
font-size: 10px;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ====== 聚光灯渐变核心 ====== */
|
|||
|
|
.spotlight-layer {
|
|||
|
|
position: absolute;
|
|||
|
|
inset: 0;
|
|||
|
|
pointer-events: none;
|
|||
|
|
z-index: 1;
|
|||
|
|
transition: opacity 0.5s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.spotlight-glow {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 0;
|
|||
|
|
right: 0;
|
|||
|
|
height: 55%;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
filter: blur(20px);
|
|||
|
|
opacity: 0;
|
|||
|
|
transition: top 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|||
|
|
opacity 0.5s ease,
|
|||
|
|
background 0.5s ease,
|
|||
|
|
height 0.5s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.spotlight-glow.active {
|
|||
|
|
opacity: 1;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* 分隔线 - 等级边界 */
|
|||
|
|
.level-divider {
|
|||
|
|
position: absolute;
|
|||
|
|
left: 52px;
|
|||
|
|
right: 0;
|
|||
|
|
height: 1px;
|
|||
|
|
background: rgba(255,255,255,0.04);
|
|||
|
|
z-index: 2;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ====== 指示条 ====== */
|
|||
|
|
.indicator-track {
|
|||
|
|
position: absolute;
|
|||
|
|
right: 6px;
|
|||
|
|
top: 8px;
|
|||
|
|
bottom: 30px;
|
|||
|
|
width: 3px;
|
|||
|
|
border-radius: 1.5px;
|
|||
|
|
background: rgba(255,255,255,0.04);
|
|||
|
|
z-index: 4;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.indicator-dot {
|
|||
|
|
position: absolute;
|
|||
|
|
right: 2px;
|
|||
|
|
width: 11px;
|
|||
|
|
height: 11px;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
transform: translate(50%, -50%);
|
|||
|
|
z-index: 5;
|
|||
|
|
transition: top 0.6s cubic-bezier(0.4, 0, 0.2, 1),
|
|||
|
|
background 0.4s ease,
|
|||
|
|
box-shadow 0.4s ease;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
@keyframes glowPulse {
|
|||
|
|
0%, 100% { opacity: 0.7; }
|
|||
|
|
50% { opacity: 1; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.indicator-dot::after {
|
|||
|
|
content: '';
|
|||
|
|
position: absolute;
|
|||
|
|
inset: -4px;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
background: inherit;
|
|||
|
|
opacity: 0.25;
|
|||
|
|
animation: glowPulse 2.5s ease-in-out infinite;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ====== 条形图 ====== */
|
|||
|
|
.bar-section {
|
|||
|
|
margin-top: 10px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bar-label {
|
|||
|
|
font-size: 11px;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
margin-bottom: 5px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bar-track {
|
|||
|
|
height: 6px;
|
|||
|
|
border-radius: 3px;
|
|||
|
|
overflow: hidden;
|
|||
|
|
display: flex;
|
|||
|
|
background: rgba(255,255,255,0.03);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bar-seg {
|
|||
|
|
height: 100%;
|
|||
|
|
transition: width 0.6s cubic-bezier(0.4, 0, 0.2, 1);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bar-seg.quiet { background: var(--quiet); }
|
|||
|
|
.bar-seg.normal { background: var(--normal); }
|
|||
|
|
.bar-seg.noisy { background: var(--noisy); }
|
|||
|
|
.bar-seg.extreme { background: var(--extreme); }
|
|||
|
|
|
|||
|
|
.bar-legend {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 10px;
|
|||
|
|
margin-top: 6px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bar-legend-item {
|
|||
|
|
display: flex;
|
|||
|
|
align-items: center;
|
|||
|
|
gap: 3px;
|
|||
|
|
font-size: 10px;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.bar-legend-dot {
|
|||
|
|
width: 5px;
|
|||
|
|
height: 5px;
|
|||
|
|
border-radius: 50%;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/* ====== Baseline ====== */
|
|||
|
|
.baseline-bands {
|
|||
|
|
position: absolute;
|
|||
|
|
inset: 0;
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
z-index: 0;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.baseline-band { flex: 1; }
|
|||
|
|
.baseline-band.extreme { background: rgba(239,68,68,0.09); }
|
|||
|
|
.baseline-band.noisy { background: rgba(245,158,11,0.08); }
|
|||
|
|
.baseline-band.normal { background: rgba(96,165,250,0.08); }
|
|||
|
|
.baseline-band.quiet { background: rgba(52,211,153,0.09); }
|
|||
|
|
|
|||
|
|
/* ====== 控制面板 ====== */
|
|||
|
|
.controls {
|
|||
|
|
max-width: 1200px;
|
|||
|
|
margin: 0 auto 32px;
|
|||
|
|
padding: 20px 24px;
|
|||
|
|
background: var(--surface);
|
|||
|
|
border: 1px solid var(--border);
|
|||
|
|
border-radius: var(--radius-component);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls-title {
|
|||
|
|
font-size: 14px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
margin-bottom: 16px;
|
|||
|
|
color: var(--text-secondary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.controls-row {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 32px;
|
|||
|
|
flex-wrap: wrap;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.control-group {
|
|||
|
|
display: flex;
|
|||
|
|
flex-direction: column;
|
|||
|
|
gap: 8px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.control-label {
|
|||
|
|
font-size: 12px;
|
|||
|
|
color: var(--text-muted);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.control-buttons {
|
|||
|
|
display: flex;
|
|||
|
|
gap: 6px;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.control-btn {
|
|||
|
|
padding: 6px 14px;
|
|||
|
|
border-radius: 8px;
|
|||
|
|
border: 1px solid var(--border);
|
|||
|
|
background: var(--surface-raised);
|
|||
|
|
color: var(--text-secondary);
|
|||
|
|
font-size: 12px;
|
|||
|
|
font-weight: 500;
|
|||
|
|
cursor: pointer;
|
|||
|
|
transition: all 0.2s ease;
|
|||
|
|
font-family: inherit;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.control-btn:hover {
|
|||
|
|
background: rgba(255,255,255,0.08);
|
|||
|
|
color: var(--text-primary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.control-btn.active-quiet { border-color: rgba(52,211,153,0.4); background: rgba(52,211,153,0.15); color: var(--quiet); }
|
|||
|
|
.control-btn.active-normal { border-color: rgba(96,165,250,0.4); background: rgba(96,165,250,0.15); color: var(--normal); }
|
|||
|
|
.control-btn.active-noisy { border-color: rgba(245,158,11,0.4); background: rgba(245,158,11,0.15); color: var(--noisy); }
|
|||
|
|
.control-btn.active-extreme { border-color: rgba(239,68,68,0.4); background: rgba(239,68,68,0.15); color: var(--extreme); }
|
|||
|
|
|
|||
|
|
/* ====== 对比标注 ====== */
|
|||
|
|
.comparison-note {
|
|||
|
|
max-width: 1200px;
|
|||
|
|
margin: 0 auto 40px;
|
|||
|
|
padding: 16px 20px;
|
|||
|
|
background: rgba(96,165,250,0.06);
|
|||
|
|
border: 1px solid rgba(96,165,250,0.12);
|
|||
|
|
border-radius: 12px;
|
|||
|
|
font-size: 13px;
|
|||
|
|
color: var(--text-secondary);
|
|||
|
|
line-height: 1.7;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.comparison-note strong {
|
|||
|
|
color: var(--text-primary);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.comparison-note .highlight {
|
|||
|
|
padding: 1px 6px;
|
|||
|
|
border-radius: 4px;
|
|||
|
|
font-size: 12px;
|
|||
|
|
font-weight: 600;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
.comparison-note .hl-quiet { background: rgba(52,211,153,0.15); color: var(--quiet); }
|
|||
|
|
.comparison-note .hl-normal { background: rgba(96,165,250,0.15); color: var(--normal); }
|
|||
|
|
.comparison-note .hl-noisy { background: rgba(245,158,11,0.15); color: var(--noisy); }
|
|||
|
|
.comparison-note .hl-extreme { background: rgba(239,68,68,0.15); color: var(--extreme); }
|
|||
|
|
</style>
|
|||
|
|
</head>
|
|||
|
|
<body>
|
|||
|
|
|
|||
|
|
<div class="page-header">
|
|||
|
|
<h1>噪音等级组件改造 · 聚光灯方案</h1>
|
|||
|
|
<p>StudyNoiseDistributionWidget 视觉升级 Mockup v2 — 局部渐变聚焦,而非全图渐变</p>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="comparison-note">
|
|||
|
|
<strong>设计理念:</strong>不是整张图都铺满渐变色带,而是只在<strong>当前等级附近</strong>产生一个柔和的聚光灯光晕。
|
|||
|
|
其余区域保持低调暗淡,让用户视线自然聚焦到当前所处等级。
|
|||
|
|
当等级切换时,光晕平滑滑动到新位置,颜色同步过渡。
|
|||
|
|
<br><br>
|
|||
|
|
<span class="highlight hl-quiet">Quiet 安静</span> →
|
|||
|
|
<span class="highlight hl-normal">Normal 正常</span> →
|
|||
|
|
<span class="highlight hl-noisy">Noisy 嘈杂</span> →
|
|||
|
|
<span class="highlight hl-extreme">Extreme 极端</span>
|
|||
|
|
点击下方按钮切换等级,观察光晕移动效果
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 控制面板 -->
|
|||
|
|
<div class="controls">
|
|||
|
|
<div class="controls-title">🎛 模拟噪音等级切换</div>
|
|||
|
|
<div class="controls-row">
|
|||
|
|
<div class="control-group">
|
|||
|
|
<div class="control-label">当前等级</div>
|
|||
|
|
<div class="control-buttons" id="level-buttons">
|
|||
|
|
<button class="control-btn" data-level="quiet" onclick="setLevel('quiet')">Quiet 安静</button>
|
|||
|
|
<button class="control-btn active-normal" data-level="normal" onclick="setLevel('normal')">Normal 正常</button>
|
|||
|
|
<button class="control-btn" data-level="noisy" onclick="setLevel('noisy')">Noisy 嘈杂</button>
|
|||
|
|
<button class="control-btn" data-level="extreme" onclick="setLevel('extreme')">Extreme 极端</button>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 当前实现 Baseline -->
|
|||
|
|
<div class="section">
|
|||
|
|
<div class="section-title">当前实现 (Baseline)</div>
|
|||
|
|
<div class="section-desc">四色硬切色带,各等级区域均匀着色,没有视觉焦点。用户需要主动寻找"我在哪个等级"。</div>
|
|||
|
|
<div class="mockup-row">
|
|||
|
|
<div class="widget-card">
|
|||
|
|
<div class="chart-header">
|
|||
|
|
<span class="chart-title">噪音等级分布</span>
|
|||
|
|
<span class="chart-badge" style="background: rgba(47,93,168,0.55);">Realtime</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="chart-area">
|
|||
|
|
<div class="baseline-bands">
|
|||
|
|
<div class="baseline-band extreme"></div>
|
|||
|
|
<div class="baseline-band noisy"></div>
|
|||
|
|
<div class="baseline-band normal"></div>
|
|||
|
|
<div class="baseline-band quiet"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="y-axis">
|
|||
|
|
<span class="y-label">Extreme</span>
|
|||
|
|
<span class="y-label">Noisy</span>
|
|||
|
|
<span class="y-label">Normal</span>
|
|||
|
|
<span class="y-label">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="curve-area">
|
|||
|
|
<svg viewBox="0 0 280 140" preserveAspectRatio="none">
|
|||
|
|
<defs>
|
|||
|
|
<linearGradient id="fill0" x1="0" y1="0" x2="0" y2="1">
|
|||
|
|
<stop offset="0%" stop-color="#EF4444" stop-opacity="0.34"/>
|
|||
|
|
<stop offset="28%" stop-color="#F59E0B" stop-opacity="0.34"/>
|
|||
|
|
<stop offset="62%" stop-color="#60A5FA" stop-opacity="0.34"/>
|
|||
|
|
<stop offset="100%" stop-color="#34D399" stop-opacity="0.34"/>
|
|||
|
|
</linearGradient>
|
|||
|
|
</defs>
|
|||
|
|
<path d="M0,95 C20,92 40,78 60,72 C80,66 100,56 120,50 C140,44 160,52 180,48 C200,44 220,38 240,42 C260,46 280,54 280,52 L280,140 L0,140 Z" fill="url(#fill0)"/>
|
|||
|
|
<path d="M0,95 C20,92 40,78 60,72 C80,66 100,56 120,50 C140,44 160,52 180,48 C200,44 220,38 240,42 C260,46 280,54 280,52" fill="none" stroke="#52AEEA" stroke-width="1.5"/>
|
|||
|
|
<circle cx="280" cy="52" r="4" fill="#fff" stroke="#52AEEA" stroke-width="1.2"/>
|
|||
|
|
<circle cx="280" cy="52" r="10" fill="rgba(82,174,234,0.2)"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
<div class="x-axis">
|
|||
|
|
<span class="x-label">-12s</span>
|
|||
|
|
<span class="x-label">-6s</span>
|
|||
|
|
<span class="x-label">Now</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 聚光灯方案 -->
|
|||
|
|
<div class="section">
|
|||
|
|
<div class="section-title">聚光灯方案 — 局部渐变聚焦</div>
|
|||
|
|
<div class="section-desc">只在当前等级附近产生柔和光晕,其余区域保持暗淡。等级切换时光晕平滑滑动,Y轴标签联动高亮,右侧指示条标注当前位置。下方条形图展示分布占比。</div>
|
|||
|
|
<div class="mockup-row">
|
|||
|
|
<!-- 标准尺寸 -->
|
|||
|
|
<div class="widget-card">
|
|||
|
|
<div class="widget-label">推荐</div>
|
|||
|
|
<div class="chart-header">
|
|||
|
|
<span class="chart-title">噪音等级分布</span>
|
|||
|
|
<span class="chart-badge" id="spot-badge" style="background: rgba(47,93,168,0.55);">Realtime</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="chart-area" id="spot-chart">
|
|||
|
|
<!-- 极淡的分隔线标记等级边界 -->
|
|||
|
|
<div class="level-divider" style="top: 25%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 50%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 75%;"></div>
|
|||
|
|
|
|||
|
|
<!-- 聚光灯光晕层 -->
|
|||
|
|
<div class="spotlight-layer">
|
|||
|
|
<div class="spotlight-glow active" id="spot-glow"
|
|||
|
|
style="top: 35%; height: 50%; background: radial-gradient(ellipse at center, rgba(96,165,250,0.14) 0%, rgba(96,165,250,0.04) 50%, transparent 80%);">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- Y轴 -->
|
|||
|
|
<div class="y-axis">
|
|||
|
|
<span class="y-label l-extreme" id="sy-extreme">Extreme</span>
|
|||
|
|
<span class="y-label l-noisy" id="sy-noisy">Noisy</span>
|
|||
|
|
<span class="y-label l-normal active" id="sy-normal">Normal</span>
|
|||
|
|
<span class="y-label l-quiet" id="sy-quiet">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 指示条 -->
|
|||
|
|
<div class="indicator-track"></div>
|
|||
|
|
<div class="indicator-dot" id="spot-dot" style="top: 55%; background: var(--normal); box-shadow: 0 0 8px rgba(96,165,250,0.5);"></div>
|
|||
|
|
|
|||
|
|
<!-- 曲线 -->
|
|||
|
|
<div class="curve-area" style="right: 18px;">
|
|||
|
|
<svg viewBox="0 0 270 140" preserveAspectRatio="none">
|
|||
|
|
<defs>
|
|||
|
|
<linearGradient id="fillSpot" x1="0" y1="0" x2="0" y2="1">
|
|||
|
|
<stop offset="0%" stop-color="#EF4444" stop-opacity="0.28"/>
|
|||
|
|
<stop offset="28%" stop-color="#F59E0B" stop-opacity="0.28"/>
|
|||
|
|
<stop offset="62%" stop-color="#60A5FA" stop-opacity="0.28"/>
|
|||
|
|
<stop offset="100%" stop-color="#34D399" stop-opacity="0.28"/>
|
|||
|
|
</linearGradient>
|
|||
|
|
</defs>
|
|||
|
|
<path d="M0,95 C20,92 40,78 60,72 C80,66 100,56 120,50 C140,44 160,52 180,48 C200,44 220,38 240,42 C260,46 270,54 270,52 L270,140 L0,140 Z" fill="url(#fillSpot)"/>
|
|||
|
|
<path d="M0,95 C20,92 40,78 60,72 C80,66 100,56 120,50 C140,44 160,52 180,48 C200,44 220,38 240,42 C260,46 270,54 270,52" fill="none" stroke="#8BE8FF" stroke-width="1.8"/>
|
|||
|
|
<circle cx="270" cy="52" r="3.5" fill="#fff" stroke="#52D6FF" stroke-width="1.2" id="spot-latest-dot"/>
|
|||
|
|
<circle cx="270" cy="52" r="9" fill="rgba(82,214,255,0.12)" id="spot-latest-glow"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="x-axis">
|
|||
|
|
<span class="x-label">-12s</span>
|
|||
|
|
<span class="x-label">-6s</span>
|
|||
|
|
<span class="x-label">Now</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 条形图 -->
|
|||
|
|
<div class="bar-section">
|
|||
|
|
<div class="bar-label">等级分布</div>
|
|||
|
|
<div class="bar-track" id="spot-bar">
|
|||
|
|
<div class="bar-seg quiet" style="width: 35%;"></div>
|
|||
|
|
<div class="bar-seg normal" style="width: 40%;"></div>
|
|||
|
|
<div class="bar-seg noisy" style="width: 18%;"></div>
|
|||
|
|
<div class="bar-seg extreme" style="width: 7%;"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="bar-legend" id="spot-legend">
|
|||
|
|
<span class="bar-legend-item"><span class="bar-legend-dot" style="background:var(--quiet);"></span>安静 35%</span>
|
|||
|
|
<span class="bar-legend-item"><span class="bar-legend-dot" style="background:var(--normal);"></span>正常 40%</span>
|
|||
|
|
<span class="bar-legend-item"><span class="bar-legend-dot" style="background:var(--noisy);"></span>嘈杂 18%</span>
|
|||
|
|
<span class="bar-legend-item"><span class="bar-legend-dot" style="background:var(--extreme);"></span>极端 7%</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 紧凑模式 -->
|
|||
|
|
<div class="widget-card">
|
|||
|
|
<div class="widget-label">紧凑模式</div>
|
|||
|
|
<div class="chart-header">
|
|||
|
|
<span class="chart-title">噪音等级分布</span>
|
|||
|
|
<span class="chart-badge" id="spot-badge-c" style="background: rgba(47,93,168,0.55);">Session</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="chart-area" style="height: 120px;" id="spot-chart-c">
|
|||
|
|
<div class="level-divider" style="top: 25%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 50%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 75%;"></div>
|
|||
|
|
|
|||
|
|
<div class="spotlight-layer">
|
|||
|
|
<div class="spotlight-glow active" id="spot-glow-c"
|
|||
|
|
style="top: 35%; height: 50%; background: radial-gradient(ellipse at center, rgba(96,165,250,0.14) 0%, rgba(96,165,250,0.04) 50%, transparent 80%);">
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="y-axis" style="width: 36px;">
|
|||
|
|
<span class="y-label l-extreme" id="syc-extreme" style="font-size:8px;">Ext</span>
|
|||
|
|
<span class="y-label l-noisy" id="syc-noisy" style="font-size:8px;">Noisy</span>
|
|||
|
|
<span class="y-label l-normal active" id="syc-normal" style="font-size:8px;">Norm</span>
|
|||
|
|
<span class="y-label l-quiet" id="syc-quiet" style="font-size:8px;">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="indicator-track" style="right: 4px; width: 2px;"></div>
|
|||
|
|
<div class="indicator-dot" id="spot-dot-c" style="right: 0; width: 8px; height: 8px; top: 55%; background: var(--normal); box-shadow: 0 0 6px rgba(96,165,250,0.4);"></div>
|
|||
|
|
|
|||
|
|
<div class="curve-area" style="left: 40px; right: 14px;">
|
|||
|
|
<svg viewBox="0 0 260 95" preserveAspectRatio="none">
|
|||
|
|
<path d="M0,65 C30,60 60,50 90,45 C120,40 150,48 180,42 C210,36 240,40 260,38 L260,95 L0,95 Z" fill="url(#fillSpot)" opacity="0.7"/>
|
|||
|
|
<path d="M0,65 C30,60 60,50 90,45 C120,40 150,48 180,42 C210,36 240,40 260,38" fill="none" stroke="#8BE8FF" stroke-width="1.4"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="x-axis" style="left: 40px;">
|
|||
|
|
<span class="x-label">-12s</span>
|
|||
|
|
<span class="x-label">-6s</span>
|
|||
|
|
<span class="x-label">Now</span>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="bar-section">
|
|||
|
|
<div class="bar-track" style="height: 4px; border-radius: 2px;">
|
|||
|
|
<div class="bar-seg quiet" style="width: 55%;"></div>
|
|||
|
|
<div class="bar-seg normal" style="width: 30%;"></div>
|
|||
|
|
<div class="bar-seg noisy" style="width: 10%;"></div>
|
|||
|
|
<div class="bar-seg extreme" style="width: 5%;"></div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<!-- 四种等级状态展示 -->
|
|||
|
|
<div class="section">
|
|||
|
|
<div class="section-title">四种等级状态一览</div>
|
|||
|
|
<div class="section-desc">同时展示四个等级的聚光灯效果,可以直观对比光晕位置、颜色和强度的差异。</div>
|
|||
|
|
<div class="mockup-row" style="grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));">
|
|||
|
|
|
|||
|
|
<div class="widget-card" style="padding: 12px;">
|
|||
|
|
<div style="font-size: 12px; font-weight: 600; color: var(--quiet); margin-bottom: 8px;">● Quiet 安静</div>
|
|||
|
|
<div class="chart-area" style="height: 100px;">
|
|||
|
|
<div class="level-divider" style="top: 25%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 50%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 75%;"></div>
|
|||
|
|
<div class="spotlight-layer">
|
|||
|
|
<div class="spotlight-glow active" style="top: 60%; height: 45%; background: radial-gradient(ellipse at center, rgba(52,211,153,0.16) 0%, rgba(52,211,153,0.04) 50%, transparent 80%);"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="y-axis" style="width: 32px; bottom: 16px;">
|
|||
|
|
<span class="y-label" style="font-size:8px;">Ext</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Noisy</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Norm</span>
|
|||
|
|
<span class="y-label l-quiet active" style="font-size:8px;">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="indicator-track" style="right: 3px; width: 2px;"></div>
|
|||
|
|
<div class="indicator-dot" style="right: 0; width: 7px; height: 7px; top: 82%; background: var(--quiet); box-shadow: 0 0 6px rgba(52,211,153,0.5);"></div>
|
|||
|
|
<div class="curve-area" style="left: 36px; right: 12px;">
|
|||
|
|
<svg viewBox="0 0 220 80" preserveAspectRatio="none">
|
|||
|
|
<path d="M0,55 C20,52 40,58 60,60 C80,62 100,65 120,63 C140,61 160,58 180,60 C200,62 220,64 220,63 L220,80 L0,80 Z" fill="url(#fillSpot)" opacity="0.5"/>
|
|||
|
|
<path d="M0,55 C20,52 40,58 60,60 C80,62 100,65 120,63 C140,61 160,58 180,60 C200,62 220,64 220,63" fill="none" stroke="#8BE8FF" stroke-width="1.2"/>
|
|||
|
|
<circle cx="220" cy="63" r="2.5" fill="#34D399" stroke="#fff" stroke-width="0.8"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="widget-card" style="padding: 12px;">
|
|||
|
|
<div style="font-size: 12px; font-weight: 600; color: var(--normal); margin-bottom: 8px;">● Normal 正常</div>
|
|||
|
|
<div class="chart-area" style="height: 100px;">
|
|||
|
|
<div class="level-divider" style="top: 25%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 50%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 75%;"></div>
|
|||
|
|
<div class="spotlight-layer">
|
|||
|
|
<div class="spotlight-glow active" style="top: 35%; height: 50%; background: radial-gradient(ellipse at center, rgba(96,165,250,0.14) 0%, rgba(96,165,250,0.04) 50%, transparent 80%);"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="y-axis" style="width: 32px; bottom: 16px;">
|
|||
|
|
<span class="y-label" style="font-size:8px;">Ext</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Noisy</span>
|
|||
|
|
<span class="y-label l-normal active" style="font-size:8px;">Norm</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="indicator-track" style="right: 3px; width: 2px;"></div>
|
|||
|
|
<div class="indicator-dot" style="right: 0; width: 7px; height: 7px; top: 55%; background: var(--normal); box-shadow: 0 0 6px rgba(96,165,250,0.5);"></div>
|
|||
|
|
<div class="curve-area" style="left: 36px; right: 12px;">
|
|||
|
|
<svg viewBox="0 0 220 80" preserveAspectRatio="none">
|
|||
|
|
<path d="M0,50 C20,48 40,42 60,38 C80,34 100,40 120,36 C140,32 160,38 180,35 C200,32 220,38 220,36 L220,80 L0,80 Z" fill="url(#fillSpot)" opacity="0.5"/>
|
|||
|
|
<path d="M0,50 C20,48 40,42 60,38 C80,34 100,40 120,36 C140,32 160,38 180,35 C200,32 220,38 220,36" fill="none" stroke="#8BE8FF" stroke-width="1.2"/>
|
|||
|
|
<circle cx="220" cy="36" r="2.5" fill="#60A5FA" stroke="#fff" stroke-width="0.8"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="widget-card" style="padding: 12px;">
|
|||
|
|
<div style="font-size: 12px; font-weight: 600; color: var(--noisy); margin-bottom: 8px;">● Noisy 嘈杂</div>
|
|||
|
|
<div class="chart-area" style="height: 100px;">
|
|||
|
|
<div class="level-divider" style="top: 25%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 50%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 75%;"></div>
|
|||
|
|
<div class="spotlight-layer">
|
|||
|
|
<div class="spotlight-glow active" style="top: 15%; height: 45%; background: radial-gradient(ellipse at center, rgba(245,158,11,0.16) 0%, rgba(245,158,11,0.04) 50%, transparent 80%);"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="y-axis" style="width: 32px; bottom: 16px;">
|
|||
|
|
<span class="y-label" style="font-size:8px;">Ext</span>
|
|||
|
|
<span class="y-label l-noisy active" style="font-size:8px;">Noisy</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Norm</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="indicator-track" style="right: 3px; width: 2px;"></div>
|
|||
|
|
<div class="indicator-dot" style="right: 0; width: 7px; height: 7px; top: 30%; background: var(--noisy); box-shadow: 0 0 6px rgba(245,158,11,0.5);"></div>
|
|||
|
|
<div class="curve-area" style="left: 36px; right: 12px;">
|
|||
|
|
<svg viewBox="0 0 220 80" preserveAspectRatio="none">
|
|||
|
|
<path d="M0,30 C20,28 40,22 60,18 C80,14 100,20 120,16 C140,12 160,18 180,15 C200,12 220,16 220,14 L220,80 L0,80 Z" fill="url(#fillSpot)" opacity="0.5"/>
|
|||
|
|
<path d="M0,30 C20,28 40,22 60,18 C80,14 100,20 120,16 C140,12 160,18 180,15 C200,12 220,16 220,14" fill="none" stroke="#FF8BE8" stroke-width="1.2"/>
|
|||
|
|
<circle cx="220" cy="14" r="2.5" fill="#F59E0B" stroke="#fff" stroke-width="0.8"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
<div class="widget-card" style="padding: 12px;">
|
|||
|
|
<div style="font-size: 12px; font-weight: 600; color: var(--extreme); margin-bottom: 8px;">● Extreme 极端</div>
|
|||
|
|
<div class="chart-area" style="height: 100px;">
|
|||
|
|
<div class="level-divider" style="top: 25%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 50%;"></div>
|
|||
|
|
<div class="level-divider" style="top: 75%;"></div>
|
|||
|
|
<div class="spotlight-layer">
|
|||
|
|
<div class="spotlight-glow active" style="top: 0%; height: 40%; background: radial-gradient(ellipse at center, rgba(239,68,68,0.18) 0%, rgba(239,68,68,0.05) 50%, transparent 80%); animation: extremePulse 2s ease-in-out infinite;"></div>
|
|||
|
|
</div>
|
|||
|
|
<div class="y-axis" style="width: 32px; bottom: 16px;">
|
|||
|
|
<span class="y-label l-extreme active" style="font-size:8px;">Ext</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Noisy</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Norm</span>
|
|||
|
|
<span class="y-label" style="font-size:8px;">Quiet</span>
|
|||
|
|
</div>
|
|||
|
|
<div class="indicator-track" style="right: 3px; width: 2px;"></div>
|
|||
|
|
<div class="indicator-dot" style="right: 0; width: 7px; height: 7px; top: 10%; background: var(--extreme); box-shadow: 0 0 8px rgba(239,68,68,0.6);"></div>
|
|||
|
|
<div class="curve-area" style="left: 36px; right: 12px;">
|
|||
|
|
<svg viewBox="0 0 220 80" preserveAspectRatio="none">
|
|||
|
|
<path d="M0,14 C20,12 40,8 60,6 C80,4 100,10 120,7 C140,4 160,8 180,5 C200,2 220,6 220,4 L220,80 L0,80 Z" fill="url(#fillSpot)" opacity="0.5"/>
|
|||
|
|
<path d="M0,14 C20,12 40,8 60,6 C80,4 100,10 120,7 C140,4 160,8 180,5 C200,2 220,6 220,4" fill="none" stroke="#FF8BE8" stroke-width="1.2"/>
|
|||
|
|
<circle cx="220" cy="4" r="2.5" fill="#EF4444" stroke="#fff" stroke-width="0.8"/>
|
|||
|
|
</svg>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
</div>
|
|||
|
|
|
|||
|
|
@keyframes extremePulse {
|
|||
|
|
0%, 100% { opacity: 0.8; }
|
|||
|
|
50% { opacity: 1; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
<script>
|
|||
|
|
const levels = {
|
|||
|
|
quiet: {
|
|||
|
|
color: '#34D399',
|
|||
|
|
cssVar: 'var(--quiet)',
|
|||
|
|
label: '安静',
|
|||
|
|
glowTop: '58%',
|
|||
|
|
glowHeight: '45%',
|
|||
|
|
glowBg: 'radial-gradient(ellipse at center, rgba(52,211,153,0.16) 0%, rgba(52,211,153,0.04) 50%, transparent 80%)',
|
|||
|
|
dotTop: '80%',
|
|||
|
|
dotShadow: '0 0 8px rgba(52,211,153,0.5)',
|
|||
|
|
badgeBg: 'rgba(15,107,73,0.8)',
|
|||
|
|
barWidths: [55, 30, 10, 5],
|
|||
|
|
barLegends: ['安静 55%', '正常 30%', '嘈杂 10%', '极端 5%'],
|
|||
|
|
latestDotColor: '#34D399',
|
|||
|
|
latestGlowColor: 'rgba(52,211,153,0.12)',
|
|||
|
|
},
|
|||
|
|
normal: {
|
|||
|
|
color: '#60A5FA',
|
|||
|
|
cssVar: 'var(--normal)',
|
|||
|
|
label: '正常',
|
|||
|
|
glowTop: '30%',
|
|||
|
|
glowHeight: '50%',
|
|||
|
|
glowBg: 'radial-gradient(ellipse at center, rgba(96,165,250,0.14) 0%, rgba(96,165,250,0.04) 50%, transparent 80%)',
|
|||
|
|
dotTop: '55%',
|
|||
|
|
dotShadow: '0 0 8px rgba(96,165,250,0.5)',
|
|||
|
|
badgeBg: 'rgba(47,93,168,0.55)',
|
|||
|
|
barWidths: [35, 40, 18, 7],
|
|||
|
|
barLegends: ['安静 35%', '正常 40%', '嘈杂 18%', '极端 7%'],
|
|||
|
|
latestDotColor: '#60A5FA',
|
|||
|
|
latestGlowColor: 'rgba(96,165,250,0.12)',
|
|||
|
|
},
|
|||
|
|
noisy: {
|
|||
|
|
color: '#F59E0B',
|
|||
|
|
cssVar: 'var(--noisy)',
|
|||
|
|
label: '嘈杂',
|
|||
|
|
glowTop: '10%',
|
|||
|
|
glowHeight: '45%',
|
|||
|
|
glowBg: 'radial-gradient(ellipse at center, rgba(245,158,11,0.16) 0%, rgba(245,158,11,0.04) 50%, transparent 80%)',
|
|||
|
|
dotTop: '28%',
|
|||
|
|
dotShadow: '0 0 8px rgba(245,158,11,0.5)',
|
|||
|
|
badgeBg: 'rgba(128,80,24,0.8)',
|
|||
|
|
barWidths: [15, 25, 42, 18],
|
|||
|
|
barLegends: ['安静 15%', '正常 25%', '嘈杂 42%', '极端 18%'],
|
|||
|
|
latestDotColor: '#F59E0B',
|
|||
|
|
latestGlowColor: 'rgba(245,158,11,0.12)',
|
|||
|
|
},
|
|||
|
|
extreme: {
|
|||
|
|
color: '#EF4444',
|
|||
|
|
cssVar: 'var(--extreme)',
|
|||
|
|
label: '极端',
|
|||
|
|
glowTop: '-5%',
|
|||
|
|
glowHeight: '40%',
|
|||
|
|
glowBg: 'radial-gradient(ellipse at center, rgba(239,68,68,0.18) 0%, rgba(239,68,68,0.05) 50%, transparent 80%)',
|
|||
|
|
dotTop: '10%',
|
|||
|
|
dotShadow: '0 0 10px rgba(239,68,68,0.6)',
|
|||
|
|
badgeBg: 'rgba(141,42,58,0.8)',
|
|||
|
|
barWidths: [5, 12, 30, 53],
|
|||
|
|
barLegends: ['安静 5%', '正常 12%', '嘈杂 30%', '极端 53%'],
|
|||
|
|
latestDotColor: '#EF4444',
|
|||
|
|
latestGlowColor: 'rgba(239,68,68,0.15)',
|
|||
|
|
}
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
function setLevel(level) {
|
|||
|
|
const cfg = levels[level];
|
|||
|
|
|
|||
|
|
document.querySelectorAll('#level-buttons .control-btn').forEach(b => {
|
|||
|
|
b.className = 'control-btn';
|
|||
|
|
});
|
|||
|
|
const activeBtn = document.querySelector(`#level-buttons .control-btn[data-level="${level}"]`);
|
|||
|
|
if (activeBtn) activeBtn.classList.add(`active-${level}`);
|
|||
|
|
|
|||
|
|
['spot', 'spot-c'].forEach(prefix => {
|
|||
|
|
const glow = document.getElementById(prefix === 'spot' ? 'spot-glow' : 'spot-glow-c');
|
|||
|
|
const dot = document.getElementById(prefix === 'spot' ? 'spot-dot' : 'spot-dot-c');
|
|||
|
|
if (glow) {
|
|||
|
|
glow.style.top = cfg.glowTop;
|
|||
|
|
glow.style.height = cfg.glowHeight;
|
|||
|
|
glow.style.background = cfg.glowBg;
|
|||
|
|
if (level === 'extreme') {
|
|||
|
|
glow.style.animation = 'extremePulse 2s ease-in-out infinite';
|
|||
|
|
} else {
|
|||
|
|
glow.style.animation = 'none';
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
if (dot) {
|
|||
|
|
dot.style.top = cfg.dotTop;
|
|||
|
|
dot.style.background = cfg.color;
|
|||
|
|
dot.style.boxShadow = cfg.dotShadow;
|
|||
|
|
}
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
['extreme', 'noisy', 'normal', 'quiet'].forEach(l => {
|
|||
|
|
const isCurrent = l === level;
|
|||
|
|
['sy', 'syc'].forEach(prefix => {
|
|||
|
|
const el = document.getElementById(`${prefix}-${l}`);
|
|||
|
|
if (el) el.classList.toggle('active', isCurrent);
|
|||
|
|
});
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const badge = document.getElementById('spot-badge');
|
|||
|
|
const badgeC = document.getElementById('spot-badge-c');
|
|||
|
|
[badge, badgeC].forEach(b => {
|
|||
|
|
if (b) { b.textContent = cfg.label; b.style.background = cfg.badgeBg; }
|
|||
|
|
});
|
|||
|
|
|
|||
|
|
const latestDot = document.getElementById('spot-latest-dot');
|
|||
|
|
const latestGlow = document.getElementById('spot-latest-glow');
|
|||
|
|
if (latestDot) latestDot.setAttribute('fill', cfg.latestDotColor);
|
|||
|
|
if (latestGlow) latestGlow.setAttribute('fill', cfg.latestGlowColor);
|
|||
|
|
|
|||
|
|
const barTrack = document.getElementById('spot-bar');
|
|||
|
|
if (barTrack) {
|
|||
|
|
const segs = barTrack.querySelectorAll('.bar-seg');
|
|||
|
|
const classes = ['quiet', 'normal', 'noisy', 'extreme'];
|
|||
|
|
cfg.barWidths.forEach((w, i) => { if (segs[i]) segs[i].style.width = w + '%'; });
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
const legend = document.getElementById('spot-legend');
|
|||
|
|
if (legend) {
|
|||
|
|
const items = legend.querySelectorAll('.bar-legend-item');
|
|||
|
|
cfg.barLegends.forEach((text, i) => { if (items[i]) items[i].childNodes[1].textContent = ' ' + text; });
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
setLevel('normal');
|
|||
|
|
</script>
|
|||
|
|
|
|||
|
|
</body>
|
|||
|
|
</html>
|