feat: add spectrum monitoring performance prototype
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# 频谱监测 WebGL2 原型性能结果
|
||||
|
||||
_第一轮可运行基线 · 2026-08-04_
|
||||
|
||||
---
|
||||
|
||||
## 📋 测试环境
|
||||
|
||||
本轮测试用于验证实现正确性、指标链路和不同负载之间的相对变化,不代表真实显卡最终性能。
|
||||
|
||||
| 项目 | 环境 |
|
||||
| --- | --- |
|
||||
| 操作系统 | macOS |
|
||||
| 浏览器 | Playwright Chromium Headless |
|
||||
| WebGL 后端 | ANGLE SwiftShader 软件渲染 |
|
||||
| 桌面视口 | 1440 × 900 |
|
||||
| 移动视口 | 390 × 844 |
|
||||
| 数据源 | Dedicated Worker 模拟 Uint8 强度帧 |
|
||||
| 渲染器 | 单 WebGL2 Context + R8 texture2DArray |
|
||||
|
||||
> ⚠️ **环境限制:** Playwright 默认无头 Chromium 未提供 WebGL2。测试通过 `--use-angle=swiftshader` 启用软件 WebGL2,因此 GPU 时间和 FPS 只能作为保守基线。真实硬件 GPU 需要在本地 Chrome、Edge 或 Safari 中重新记录。
|
||||
|
||||
## 🔬 模拟负载模型
|
||||
|
||||
模拟器定位为“接收端已经解码、校准后的频谱强度帧”,而不是原始 IQ 采样或浏览器内 FFT。这样能独立测量数据传递、纹理上传、曲线和瀑布渲染能力,不会把 DSP 计算混入前端展示指标。
|
||||
|
||||
### 已模拟内容
|
||||
|
||||
| 特征 | 实现 |
|
||||
| --- | --- |
|
||||
| 噪声统计 | 近似 FFT 单频点功率分布,不使用均匀随机抖动 |
|
||||
| 接收通带 | 边缘衰减、固定纹波、频段校准偏差 |
|
||||
| 时间特征 | 噪声逐帧变化、噪声底慢漂移、信号慢衰落 |
|
||||
| 窄带信号 | 固定载波和近似高斯频谱裙边 |
|
||||
| 宽带信号 | 平顶占用带宽、滚降边沿和带内功率纹理 |
|
||||
| 动态信号 | 突发、跳频和线性扫频 |
|
||||
| 可重复性 | 固定随机种子,时间由帧序号和刷新率确定 |
|
||||
| 场景配置 | 安静频段、混合业务、密集信号、突发/跳频 |
|
||||
|
||||
信号数量按总频宽(GHz)和场景密度计算,信号占用带宽、跳频步进与扫频范围先以 MHz 定义,再映射到 FFT bin。因而把同一总频宽切成 1、32 或 64 个显示窗口不会改变物理信号集合;窗口数与每窗口 FFT 点数只改变总数据点数和渲染负载。
|
||||
|
||||
噪声底参数表示完成 RBW、窗函数、接收机噪声系数和校准后的“每 FFT bin dBm”,不是 `-174 dBm/Hz` 热噪声密度。正式接入时应直接采用设备上报值。
|
||||
|
||||
### 未模拟内容
|
||||
|
||||
- 原始 IQ 采样率、ADC 量化和 IQ 不平衡
|
||||
- FFT 窗函数旁瓣的精确数学响应
|
||||
- RBW/VBW、检波器模式和平均算法
|
||||
- AGC、前端压缩、互调、镜像和杂散
|
||||
- WebSocket/TCP 协议开销及服务端排队
|
||||
|
||||
因此,当前“强度流”指标是 `窗口数 × FFT 点数 × 更新频率 × 8 bit`,代表 Worker 输出到渲染器的数据量。若真实协议使用 `Int16` 或 `Float32`,网络带宽分别约为该值的 2 倍或 4 倍,但在 Worker 归一化为 `Uint8` 后,GPU 上传负载仍与当前测试一致。
|
||||
|
||||
## 📊 测试结果
|
||||
|
||||
| 场景 | FPS | 接收 | 吞吐 | CPU 上传 | CPU 提交 | GPU | 延迟 | 纹理 |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| 移动轻载:4 × 1024 × 30 Hz,96 行 | 60 | 29.5 Hz | 0.97 Mb/s | 0.00 ms | 0.10 ms | 1.80 ms | 2 ms | 0.4 MiB |
|
||||
| 桌面基准:32 × 1024 × 30 Hz,96 行 | 25 | 31.0 Hz | 8.12 Mb/s | 0.10 ms | 0.10 ms | 13.77 ms | 17 ms | 3.0 MiB |
|
||||
| 桌面高载:64 × 4096 × 20 Hz,128 行 | 5 | 20.3 Hz | 42.62 Mb/s | 0.30 ms | 0.30 ms | 59.82 ms | 19 ms | 32.3 MiB |
|
||||
|
||||
改进信号模型后补充复测:
|
||||
|
||||
| 场景 | FPS | 接收 | 强度流 | CPU 上传 | CPU 提交 | GPU | 延迟 | 纹理 |
|
||||
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
|
||||
| 混合业务:32 × 1024 × 30 Hz,96 行 | 24 | 31.0 Hz | 8.13 Mb/s | 0.00 ms | 0.20 ms | 7.78 ms | 11 ms | 3.0 MiB |
|
||||
| 密集信号:64 × 4096 × 20 Hz,128 行 | 10 | 19.4 Hz | 40.59 Mb/s | 0.20 ms | 0.20 ms | 39.53 ms | 49 ms | 32.3 MiB |
|
||||
|
||||
丢弃帧统计为应用负载以来的累计值,包含页面启动和配置切换阶段,不能直接比较不同测试时长。它的主要用途是判断最新帧策略是否正在主动控制延迟。
|
||||
|
||||
## 💡 结果分析
|
||||
|
||||
### 数据通路达到目标频率
|
||||
|
||||
三个场景的数据接收率均接近配置值。64 路场景约 42.6 Mb/s,与 `64 × 4096 × 20 × 8 bit` 的理论强度数据量一致,说明 Worker、可转移 ArrayBuffer 和主线程接收链路可以承载该测试规模。
|
||||
|
||||
### GPU 填充成为高负载瓶颈
|
||||
|
||||
CPU 上传和绘制命令提交均低于 0.5 ms,但软件 GPU 时间从轻载的 1.8 ms 增长到高载的约 59.8 ms。瓶颈主要来自 64 个窗口、2936 像素画布高度和瀑布区域填充,而不是 JavaScript 绘制循环。
|
||||
|
||||
### 最新帧策略保持低延迟
|
||||
|
||||
高载时 FPS 低于数据频率,原型会覆盖待处理旧帧而不是形成队列。端到端延迟仍保持约 19 ms,证明主动丢弃中间帧可以避免延迟持续增长。
|
||||
|
||||
### 响应式布局通过基础验证
|
||||
|
||||
390 像素移动视口下页面水平溢出为 0,控制项自动换行,四个窗口使用单列布局。桌面 32 路使用四列布局,曲线、阈值、瀑布、标签和框选区域未出现重叠。
|
||||
|
||||
## ✅ 已验证功能
|
||||
|
||||
- Worker 按窗口数、FFT 点数和刷新率生成数据
|
||||
- ArrayBuffer 回收池与最新帧覆盖策略
|
||||
- 运行时重建 R8 `texture2DArray`
|
||||
- 单 Canvas 绘制 1 至 64 个频率窗口
|
||||
- 当前曲线、GPU 环形瀑布和阈值超限着色
|
||||
- 矩形框选与频率/dBm 结果换算
|
||||
- FPS、接收率、吞吐、CPU、GPU、延迟、内存和丢帧指标
|
||||
- 配置切换版本隔离,旧尺寸帧不会进入新纹理
|
||||
- WebGL2 不可用时显示明确错误状态
|
||||
|
||||
## 🔍 下一轮建议
|
||||
|
||||
1. 在目标部署设备的硬件 Chrome/Edge 上记录同一测试矩阵
|
||||
2. 增加固定画布高度模式,区分“同时绘制所有窗口”和“只绘制可见窗口”
|
||||
3. 为 4096/8192 点曲线增加屏幕空间 `min/max` LOD 对照测试
|
||||
4. 连续运行 30 分钟记录 JS Heap、GPU 纹理和丢帧变化
|
||||
5. 若硬件 GPU 在 32 路基准下仍无法稳定 60 FPS,再评估按脏帧绘制、降低 DPR 或可见区域裁剪
|
||||
|
||||
---
|
||||
|
||||
_最后更新:2026-08-04_
|
||||
@@ -0,0 +1,240 @@
|
||||
# 无线电频谱与瀑布图前端渲染方案调研
|
||||
|
||||
_技术选型与性能验证方案 · Vue Web 前端 · 2026-08-04_
|
||||
|
||||
---
|
||||
|
||||
## 📋 摘要
|
||||
|
||||
本文面向全频或多频率窗口的实时监测页面,比较商业图表库、开源信号图表库和专用 WebGL2 渲染器。目标页面需要同时显示实时频谱曲线与瀑布图,支持阈值、框选、缩放和游标,并允许在一个页面中显示 1 个全频窗口或 16/32/64 个频率窗口。
|
||||
|
||||
调研结论是:允许商业授权时,SciChart.js 是功能完整度和开发效率较均衡的方案;必须采用宽松开源许可证时,没有现成组件能同时满足多窗口、高刷新率、瀑布图和完整交互。开源路线应采用 Vue 管理控制面、Web Worker 处理数据、单 WebGL2 上下文绘制全部窗口,并以 GPU 环形纹理保存瀑布历史。
|
||||
|
||||
当前性能原型选择开源专用方案,以验证浏览器真实容量上限,同时保留 SciChart.js 作为后续商业方案对照组。
|
||||
|
||||
## 🎯 需求与边界
|
||||
|
||||
### 核心需求
|
||||
|
||||
- 支持 1 个连续全频视图,也支持 4/8/16/32/64 个频率窗口
|
||||
- 每个窗口同时显示当前频谱曲线与历史瀑布图
|
||||
- 支持阈值线、超阈值着色、矩形框选、缩放和频率游标
|
||||
- 支持可配置 FFT 点数、数据刷新率、瀑布深度和频率范围
|
||||
- 高频数据不能进入 Vue 深层响应式系统
|
||||
- 数据到达速度超过渲染速度时保持低延迟,不积压旧帧
|
||||
|
||||
### 非目标
|
||||
|
||||
- 不定义正式后端协议和鉴权方案
|
||||
- 不处理设备控制、解调和信号识别算法
|
||||
- 不追求在移动设备上同时展示 64 个完整窗口
|
||||
- 不把百万 FFT 点逐点映射到不足数千像素的屏幕
|
||||
|
||||
> 📌 **关键定义:** “全频段”描述连续频率范围,不等于必须将全部原始 FFT 点直接提交给 GPU。缩放前必须根据视口进行保峰值的多级降采样。
|
||||
|
||||
## 🔬 调研方法
|
||||
|
||||
本次调研核对了 npm 最新版本元数据、项目许可证、公开 API、官方示例和实际开源实现。候选方案按五个维度评估:曲线、瀑布、多图资源模型、交互能力和授权风险。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
accTitle: 频谱渲染技术选型流程
|
||||
accDescr: 从功能筛选、渲染模型检查、许可证审查到性能原型验证的完整选型流程
|
||||
|
||||
requirements[📋 明确负载模型] --> candidates[🔍 筛选候选库]
|
||||
candidates --> rendering{⚡ GPU 增量渲染?}
|
||||
rendering -->|是| licensing{🔐 许可可接受?}
|
||||
rendering -->|否| baseline[📊 仅作功能基线]
|
||||
licensing -->|是| benchmark[🧪 进入性能测试]
|
||||
licensing -->|否| custom[🔧 专用 WebGL2]
|
||||
custom --> benchmark
|
||||
benchmark --> decision([✅ 根据实测定型])
|
||||
|
||||
classDef process fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
|
||||
classDef decision fill:#fef9c3,stroke:#ca8a04,stroke-width:2px,color:#713f12
|
||||
classDef success fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
|
||||
class requirements,candidates,baseline,custom,benchmark process
|
||||
class rendering,licensing decision
|
||||
class decision success
|
||||
```
|
||||
|
||||
## 📊 方案对比
|
||||
|
||||
### 综合比较
|
||||
|
||||
| 方案 | 渲染内核 | 瀑布能力 | 多窗口模型 | 交互 | 许可证 | 结论 |
|
||||
| --- | --- | --- | --- | --- | --- | --- |
|
||||
| SciChart.js 5.2.62 | WebGL2 + WASM | Uniform Heatmap | 单 Surface + SubCharts | 完整 | 商业 | 商业首选 |
|
||||
| LightningChart JS 9.0.0 | WebGL | Scrolling Heatmap | Dashboard | 完整 | 商业 | 性能强,许可复杂 |
|
||||
| ECharts 6.1.0 | Canvas/SVG | Heatmap | 多 Grid/实例 | 完整 | Apache-2.0 | 低频功能基线 |
|
||||
| Highcharts 13.0.0 | SVG + Boost | Heatmap | 多 Chart | 完整 | 商业 | 通用性强,针对性弱 |
|
||||
| SigPlot 3.1.7 | Canvas2D | 流式 2D Layer | 多实例 | 较完整 | Apache-2.0 | SDR 开源基线 |
|
||||
| uPlot 1.6.32 | Canvas2D | 无内置 | 多实例 | 插件 | MIT | 只适合曲线 |
|
||||
| webgl-plot 1.1.2 | WebGL | 无内置 | 需自研 | 需自研 | MIT | 曲线底层组件 |
|
||||
| gl-spectrogram 1.1.8 | WebGL | 内置 | 多实例 | 很弱 | MIT | 仅作代码参考 |
|
||||
| OpenWebRX | Canvas2D | 内置 | 单接收视图 | SDR 交互 | AGPL-3.0 | 架构参考 |
|
||||
| 专用 WebGL2 | WebGL2 | 环形纹理 | 单上下文分视口 | 按需实现 | 项目自有 | 开源性能首选 |
|
||||
|
||||
### 商业组件
|
||||
|
||||
SciChart.js 提供 WebGL2/WASM 渲染、Uniform Heatmap、Box/Line Annotation、RubberBand 选择及 SubCharts API。其公开类型说明明确建议:需要大量图表同时更新时,应使用单 Surface 配合 SubCharts,而不是创建大量独立 WebGL 上下文。[^1]
|
||||
|
||||
LightningChart JS 提供 `HeatmapScrollingGridSeries`、Spectrogram 示例、多通道实时曲线和 Dashboard。官方给出的性能目标非常激进,但许可包含开发与部署授权、联网校验和特定用途约束,采购前需要单独确认。[^2]
|
||||
|
||||
### 通用开源图表库
|
||||
|
||||
ECharts 的 `brush`、`markLine`、`dataZoom` 和 Heatmap 能快速完成交互原型,但它的主渲染器基于 Canvas/SVG 场景图。大量热力图单元和高频 `setOption` 更新会增加主线程和对象管理压力,因此不作为 32/64 窗口高刷新率主视图。[^3]
|
||||
|
||||
uPlot 是高效的 Canvas2D 时序曲线库,但项目文档明确建议在海量 60 FPS 流式信号场景使用 WebGL;同时没有内置瀑布图。[^4] webgl-plot 能以 WebGL 绘制实时波形,并支持 OffscreenCanvas,但缺少瀑布、坐标轴和标注系统。[^5]
|
||||
|
||||
### SDR 与瀑布开源实现
|
||||
|
||||
SigPlot 面向软件无线电,具有一维、二维流式 Layer 和 SDR 交互,采用 Apache-2.0 许可证。其二维实现主要更新 Canvas 图像缓冲,因此适合功能基线,不应在未经测试时假设能承载 64 个窗口。[^6]
|
||||
|
||||
gl-spectrogram 使用 WebGL 双纹理和 Framebuffer 实现瀑布,但每次 `push` 会将已有纹理整体平移到另一纹理。该方式适合单个音频频谱图,不适合大量窗口;更合理的做法是保持纹理不动,仅循环更新一行。[^7]
|
||||
|
||||
OpenWebRX 是成熟的 SDR 应用参考。其前端逐行创建 `ImageData`、执行 JavaScript 颜色映射,再调用 `putImageData` 写入多个 Canvas;许可证为 AGPL-3.0。它适合研究交互和协议,不适合作为宽松授权的高性能组件依赖。[^8]
|
||||
|
||||
## 💡 推荐架构
|
||||
|
||||
### 数据与渲染通路
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
accTitle: 实时频谱前端数据通路
|
||||
accDescr: 模拟器或 WebSocket 数据经过 Worker 解码和降采样后,以最新帧策略进入单 WebGL2 渲染器
|
||||
|
||||
source[🌐 模拟器或 WebSocket] --> worker[⚙️ Worker 解码与 LOD]
|
||||
worker --> latest[(💾 最新帧缓冲)]
|
||||
latest --> upload[⚡ 上传当前纹理行]
|
||||
upload --> waterfall[📊 GPU 环形瀑布]
|
||||
upload --> curve[📈 当前频谱曲线]
|
||||
controls[🔧 Vue 控制与交互] --> renderer[⚙️ 单 WebGL2 Surface]
|
||||
waterfall --> renderer
|
||||
curve --> renderer
|
||||
renderer --> display([✅ 多频率窗口])
|
||||
|
||||
classDef process fill:#dbeafe,stroke:#2563eb,stroke-width:2px,color:#1e3a5f
|
||||
classDef data fill:#ede9fe,stroke:#7c3aed,stroke-width:2px,color:#3b0764
|
||||
classDef success fill:#dcfce7,stroke:#16a34a,stroke-width:2px,color:#14532d
|
||||
class source,worker,upload,waterfall,curve,controls,renderer process
|
||||
class latest data
|
||||
class display success
|
||||
```
|
||||
|
||||
### GPU 环形纹理
|
||||
|
||||
瀑布纹理使用 `R8` 或 `R16F` 保存归一化强度。每个 FFT 帧只执行一行 `texSubImage2D`,写入位置按以下方式循环:
|
||||
|
||||
```text
|
||||
writeRow = (writeRow + 1) % historyRows
|
||||
sampleRow = (writeRow - screenRow + historyRows) % historyRows
|
||||
```
|
||||
|
||||
Fragment Shader 通过 `sampleRow` 改变显示顺序,不移动历史纹理。颜色使用一维 LUT 纹理完成映射。当前曲线可以从最新一行采样,避免复制第二份强度数据。
|
||||
|
||||
多窗口共享一个 WebGL2 Context,通过 `viewport` 和 `scissor` 划分绘制区域。这样不会触发浏览器 WebGL Context 数量限制,也降低重复纹理、着色器和状态切换成本。
|
||||
|
||||
### Vue 集成原则
|
||||
|
||||
- Vue 只保存配置、布局、阈值、选区和统计值
|
||||
- FFT 数组保持为非响应式 TypedArray
|
||||
- Web Worker 使用可转移 ArrayBuffer 池,避免持续分配
|
||||
- 主线程只保留最新帧,旧帧直接回收
|
||||
- `requestAnimationFrame` 决定绘制节奏,数据接收不直接触发 Vue Render
|
||||
- 阈值和框选使用轻量覆盖层,指针移动时才更新
|
||||
|
||||
## ⚡ 容量模型
|
||||
|
||||
### 数据带宽
|
||||
|
||||
使用 16 位强度值时:
|
||||
|
||||
```text
|
||||
带宽 = 窗口数 × 每窗口 FFT 点数 × 2 字节 × 更新频率
|
||||
```
|
||||
|
||||
| 场景 | 计算规模 | 约合带宽 |
|
||||
| --- | ---: | ---: |
|
||||
| 32 个窗口 | 32 × 2048 × 30 Hz | 3.75 MiB/s |
|
||||
| 64 个窗口 | 64 × 4096 × 20 Hz | 10 MiB/s |
|
||||
| 单个全频 | 1,048,576 × 20 Hz | 40 MiB/s |
|
||||
|
||||
全频缩放前的有效水平分辨率通常只有 1,000 至 4,000 像素。曲线应按像素保留 `min/max` 包络,瀑布按像素保留 `max` 或可配置聚合;否则既浪费带宽,也可能因平均降采样丢失窄带峰值。
|
||||
|
||||
### GPU 内存
|
||||
|
||||
采用单字节强度纹理时:
|
||||
|
||||
```text
|
||||
瀑布内存 = 窗口数 × FFT 点数 × 历史行数
|
||||
```
|
||||
|
||||
| 场景 | 纹理规模 | 强度纹理内存 |
|
||||
| --- | ---: | ---: |
|
||||
| 32 × 2048 × 256 | 16,777,216 texels | 16 MiB |
|
||||
| 64 × 4096 × 256 | 67,108,864 texels | 64 MiB |
|
||||
| 1M × 512 | 536,870,912 texels | 512 MiB |
|
||||
|
||||
最后一种布局不合理,必须在进入瀑布纹理前完成 LOD。
|
||||
|
||||
## 🧪 性能验证计划
|
||||
|
||||
### 测试矩阵
|
||||
|
||||
| 维度 | 测试值 |
|
||||
| --- | --- |
|
||||
| 窗口数 | 1、8、16、32、64 |
|
||||
| FFT 点数 | 512、1024、2048、4096、8192 |
|
||||
| 数据频率 | 10、20、30、60 Hz |
|
||||
| 瀑布深度 | 64、128、256、512 行 |
|
||||
| 页面布局 | 全频单图、多列窗口 |
|
||||
| 交互 | 阈值拖动、框选、缩放、游标 |
|
||||
|
||||
### 验收指标
|
||||
|
||||
| 指标 | 目标 |
|
||||
| --- | ---: |
|
||||
| P95 帧耗时 | 小于 16.7 ms |
|
||||
| 交互反馈延迟 | 小于 50 ms |
|
||||
| 数据到显示延迟 | 小于 100 ms |
|
||||
| 主线程长任务 | 10 分钟内无持续出现 |
|
||||
| 内存 | 30 分钟运行无持续增长 |
|
||||
| 数据积压 | 不积压,允许合并中间帧 |
|
||||
|
||||
性能页面必须显示实际 FPS、数据接收率、上传耗时、绘制耗时、丢弃帧数、估算吞吐和纹理内存。测试结果只能代表指定浏览器、GPU、分辨率和设备像素比,不能直接外推到全部终端。
|
||||
|
||||
## ✅ 选型结论
|
||||
|
||||
当前采用以下决策:
|
||||
|
||||
1. 使用专用 WebGL2 GPU 环形纹理实现开源性能基线
|
||||
2. 使用 Vue 构建控制面,不让 Vue 管理实时 FFT 数组
|
||||
3. 使用 Worker 模拟后端并生成二进制 TypedArray 数据
|
||||
4. 使用单 WebGL2 Context 绘制全部频率窗口
|
||||
5. 将 SigPlot 保留为开源功能对照,不作为最终内核
|
||||
6. 将 SciChart.js 保留为商业对照,待开源基线结果出来后再决定是否评估试用版
|
||||
|
||||
选择专用实现并非预先认定其一定优于商业库,而是为了先获得不受许可约束的真实容量数据,并明确浏览器、GPU、数据带宽和布局的性能边界。
|
||||
|
||||
## 🔗 参考资料
|
||||
|
||||
[^1]: SciChart. (2026). "SciChart.js npm package and SubCharts APIs." _npm / SciChart Documentation_. <https://www.npmjs.com/package/scichart>
|
||||
|
||||
[^2]: LightningChart. (2026). "LightningChart JS interactive examples and heatmap features." _LightningChart_. <https://lightningchart.com/lightningchart-js-interactive-examples/>
|
||||
|
||||
[^3]: Apache ECharts. (2026). "Canvas vs. SVG." _Apache ECharts Handbook_. <https://echarts.apache.org/handbook/en/best-practices/canvas-vs-svg/>
|
||||
|
||||
[^4]: uPlot Contributors. (2025). "uPlot performance and streaming guidance." _GitHub_. <https://github.com/leeoniya/uPlot>
|
||||
|
||||
[^5]: Chitnis, D. (2026). "webgl-plot: high-performance 2D plotting." _GitHub_. <https://github.com/danchitnis/webgl-plot>
|
||||
|
||||
[^6]: Spectric Labs. (2025). "SigPlot: interactive plotting for SDR applications." _GitHub_. <https://github.com/spectriclabs/sigplot>
|
||||
|
||||
[^7]: audio-lab. (2022). "gl-spectrogram WebGL renderer." _GitHub_. <https://github.com/audio-lab/gl-spectrogram>
|
||||
|
||||
[^8]: OpenWebRX Contributors. (2026). "OpenWebRX source and AGPL license." _GitHub_. <https://github.com/jketterl/openwebrx>
|
||||
|
||||
---
|
||||
|
||||
_最后更新:2026-08-04_
|
||||
+142
@@ -0,0 +1,142 @@
|
||||
# 频谱监测性能实验台 UI Spec
|
||||
|
||||
_实现约束与验收基准 · Web / Vue · 2026-08-04_
|
||||
|
||||
---
|
||||
|
||||
## 📋 需求拆解
|
||||
|
||||
| 项目 | 定义 |
|
||||
| --- | --- |
|
||||
| 页面类型 | 高密度工程监测台 |
|
||||
| 目标用户 | 频谱监测、无线电和前端性能工程师 |
|
||||
| 核心任务 | 调整负载参数并观察曲线、瀑布及性能指标 |
|
||||
| 首屏主信息 | 运行状态、FPS、数据率、渲染耗时、频谱视图 |
|
||||
| 次要信息 | GPU 内存估算、丢帧、端到端延迟、选区结果 |
|
||||
| 平台 | 桌面 Web 优先,平板可查看,移动端仅用于诊断 |
|
||||
| 数据源 | Web Worker 模拟二进制强度帧 |
|
||||
|
||||
必须包含正常、暂停、配置应用中、WebGL 不支持和 Worker 异常状态。页面不包含营销内容,不使用装饰型卡片;控制条和性能条保持紧凑,主区域用于频谱数据。
|
||||
|
||||
## 🎯 页面规格
|
||||
|
||||
```yaml
|
||||
screen:
|
||||
name: 频谱监测性能实验台
|
||||
surface: web
|
||||
type: dashboard
|
||||
goal: 测量全频或多窗口曲线与瀑布图的浏览器性能边界
|
||||
target_users:
|
||||
- 频谱监测工程师
|
||||
- 前端性能工程师
|
||||
primary_task: 配置数据规模并在交互过程中判断是否满足性能目标
|
||||
information_density: high
|
||||
visual_style: 安静、专业、偏仪器界面
|
||||
|
||||
platform:
|
||||
stack: Vue 3 + TypeScript + Web Worker + WebGL2
|
||||
existing_components:
|
||||
- lucide-vue-next
|
||||
state_management: Vue Composition API local state
|
||||
routing_or_navigation: 单页面
|
||||
design_system: 项目内紧凑变量与原生表单控件
|
||||
|
||||
layout:
|
||||
shell: 固定标题与控制区、性能状态条、可滚动频谱区域
|
||||
max_width_or_device_rule: 桌面占满可用宽度,最小支持 768px
|
||||
background: 中性深灰仪器背景
|
||||
content_container: 全宽无装饰外卡片
|
||||
regions:
|
||||
- id: control_bar
|
||||
name: 测试控制
|
||||
priority: high
|
||||
position: 顶部
|
||||
adaptive_behavior: 窄屏换行
|
||||
- id: metrics_bar
|
||||
name: 性能指标
|
||||
priority: high
|
||||
position: 控制区下方
|
||||
adaptive_behavior: 自动换列
|
||||
- id: spectrum_surface
|
||||
name: 频谱与瀑布
|
||||
priority: high
|
||||
position: 主内容区
|
||||
adaptive_behavior: 1 至 4 列响应式网格
|
||||
- id: selection_feedback
|
||||
name: 选区结果
|
||||
priority: medium
|
||||
position: 性能条右侧
|
||||
adaptive_behavior: 窄屏独占一行
|
||||
|
||||
interactions:
|
||||
- name: 应用负载配置
|
||||
trigger: 点击应用按钮
|
||||
result: 重建 Worker 数据规模和 GPU 纹理
|
||||
feedback: 指标归零并显示运行状态
|
||||
risk: none
|
||||
- name: 暂停数据流
|
||||
trigger: 点击暂停按钮
|
||||
result: Worker 停止生成帧
|
||||
feedback: 状态显示已暂停
|
||||
risk: none
|
||||
- name: 调整阈值
|
||||
trigger: 拖动阈值滑块
|
||||
result: 所有曲线更新阈值线和超限颜色
|
||||
feedback: 实时显示 dBm 数值
|
||||
risk: none
|
||||
- name: 框选频率区域
|
||||
trigger: 在任一窗口按下并拖动
|
||||
result: 显示矩形和频率范围
|
||||
feedback: 性能条显示窗口编号与起止频率
|
||||
risk: none
|
||||
|
||||
tokens:
|
||||
color_style: 中性深色背景,青绿数据,黄色阈值,红色告警
|
||||
primary: "#2dd4bf"
|
||||
success: "#55d187"
|
||||
warning: "#f5c451"
|
||||
danger: "#ff735f"
|
||||
background: "#101416"
|
||||
typography: 系统无衬线字体与等宽数字
|
||||
spacing: 4/8/12/16/24
|
||||
radius: 4px
|
||||
elevation_or_shadow: 无大面积阴影,仅使用边框分层
|
||||
density: compact
|
||||
|
||||
adaptive:
|
||||
desktop: 1440px 以上显示四列频率窗口
|
||||
tablet: 768 至 1199px 显示两列
|
||||
mobile: 低于 768px 显示单列并允许控制条换行
|
||||
text_scale: 支持浏览器 125% 缩放且不重叠
|
||||
orientation: 桌面横向优先
|
||||
|
||||
accessibility:
|
||||
semantics: Canvas 具有描述文本,每个频率窗口具有可访问名称
|
||||
focus_order: 配置控件、运行控制、频谱窗口
|
||||
labels: 图标按钮必须提供 aria-label 和 title
|
||||
contrast: 文本和状态色满足深色背景可读性
|
||||
motion: prefers-reduced-motion 下关闭非必要过渡
|
||||
touch_targets: 交互控件最小高度 32px
|
||||
```
|
||||
|
||||
## ✅ 验收标准
|
||||
|
||||
1. 支持 1、8、16、32、64 个窗口以及 512 至 8192 FFT 点
|
||||
2. 每个窗口同时出现当前曲线、阈值线和瀑布历史
|
||||
3. 参数应用后不刷新页面,指标和纹理正确重置
|
||||
4. 框选后显示频率范围,选择层不改变 Canvas 尺寸
|
||||
5. 实时显示 FPS、接收频率、吞吐、上传、绘制、延迟、丢帧和纹理内存
|
||||
6. FFT TypedArray 不进入 Vue 深层响应式状态
|
||||
7. 桌面、平板和移动宽度无文本重叠或水平溢出
|
||||
8. WebGL2 初始化失败时显示明确错误,而不是空白画布
|
||||
|
||||
## 🔍 待实测问题
|
||||
|
||||
- 目标设备在 64 × 4096 × 20 Hz 下的 Worker 生成能力
|
||||
- 不同 GPU 对 `R8 texture2DArray` 连续行上传的耗时差异
|
||||
- 画布高度、设备像素比和多窗口布局对填充率的影响
|
||||
- 8192 点曲线使用原始 `LINE_STRIP` 时是否需要屏幕空间 LOD
|
||||
|
||||
---
|
||||
|
||||
_最后更新:2026-08-04_
|
||||
Reference in New Issue
Block a user