Files
LanMountainDesktop/mockup-noise-level.html

899 lines
31 KiB
HTML
Raw Normal View History

<!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>
&nbsp;点击下方按钮切换等级,观察光晕移动效果
</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>