diff --git a/src/components/iframe-page-comps/Iframe-PlotlyJs-Comp.vue b/src/components/iframe-page-comps/Iframe-PlotlyJs-Comp.vue index 25532d2..71d67d9 100644 --- a/src/components/iframe-page-comps/Iframe-PlotlyJs-Comp.vue +++ b/src/components/iframe-page-comps/Iframe-PlotlyJs-Comp.vue @@ -10,9 +10,9 @@ const iframeRef = useTemplateRef('iframeRef'); let contentWindow: null | WindowWithPlotly = null; let 频谱图Element: import('plotly.js-dist-min').PlotlyHTMLElement | null = null; -// let 瀑布图Element: import('plotly.js-dist-min').PlotlyHTMLElement | null = null; +let 瀑布图Element: import('plotly.js-dist-min').PlotlyHTMLElement | null = null; -let _readyPromiseReslove = () => {}; +let _readyPromiseReslove: () => void; const readyPromise = new Promise((resolve) => { _readyPromiseReslove = resolve; }); @@ -23,10 +23,12 @@ const 频谱瀑布图Layout = { title: '频率 (Hz)', // range: [0, 22_050], showgrid: false, + tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读) }, yaxis: { title: '时间步', showgrid: false, + tickformat: ',d', // 设置为带逗号的整数格式 (推荐,更易读) }, margin: { l: 60, r: 40, b: 40, t: 60 }, }; @@ -49,14 +51,30 @@ const 频谱图Layout = { margin: { l: 60, r: 40, b: 40, t: 60 }, } satisfies Partial; +// 存储瀑布图数据的数组,限制最大行数以避免内存问题 +const 瀑布图数据: number[][] = []; +const 最大时间步 = 50; // 减少时间步长以避免画布大小超出限制 +const 数据缩减因子 = 10; // 每10个数据点取平均值以减少数据量 + +// 辅助函数:对数据进行缩减处理 +function 缩减数据(数据: number[]): number[] { + const 缩减后数据: number[] = []; + for (let i = 0; i < 数据.length; i += 数据缩减因子) { + const 片段 = 数据.slice(i, i + 数据缩减因子); + const 平均值 = 片段.reduce((sum, val) => sum + val, 0) / 片段.length; + 缩减后数据.push(平均值); + } + return 缩减后数据; +} + defineExpose({ 添加数据: async (DB数据: I数据, FFT大小: number /* 也叫快速傅里叶变换大小 */, 采样率: number) => { const 频率分辨率 = 采样率 / FFT大小; + await readyPromise; { // 频谱图 console.debug('[添加数据被调用]', `数据.length :>> `, DB数据.length); - await readyPromise; // 先清空之前的数据 await contentWindow!.Plotly.react(频谱图Element!, [], 频谱图Layout); const x频率数据 = Array.from({ length: DB数据.length }, (_, i) => i * 频率分辨率); @@ -65,11 +83,40 @@ defineExpose({ y: DB数据, type: 'scatter', line: { color: 'blue' }, + hovertemplate: '频率: %{x:,d} Hz
幅度: %{y:.2f} dB', // 自定义悬停文本 }); } { // 瀑布图 + // 对数据进行缩减处理 + const 缩减后DB数据 = 缩减数据([...DB数据]); + console.debug(`缩减后DB数据.length :>> `, 缩减后DB数据.length); + // 将新数据添加到瀑布图数据数组的顶部 + 瀑布图数据.unshift(缩减后DB数据); + // 限制数组长度 + if (瀑布图数据.length > 最大时间步) { + 瀑布图数据.pop(); + } + // 准备热图数据 + const x频率数据 = Array.from({ length: 缩减后DB数据.length }, (_, i) => i * 频率分辨率 * 数据缩减因子); + const y时间步数据 = Array.from({ length: 瀑布图数据.length }, (_, i) => 瀑布图数据.length - 1 - i); + // 更新瀑布图 + await contentWindow!.Plotly.react( + 瀑布图Element!, + [ + { + z: 瀑布图数据, + x: x频率数据, + y: y时间步数据, + type: 'heatmap', + colorscale: 'Viridis', // 颜色映射,可以根据需要调整 + showscale: true, // 显示颜色条 + hovertemplate: '时间步: %{y}
频率: %{x:,d} Hz
幅度: %{z:.2f} dB', // 自定义悬停文本 + }, + ], + 频谱瀑布图Layout, + ); } }, }); diff --git a/src/pages/Page/iframe-page/Iframe-PlotlyJs.page.vue b/src/pages/Page/iframe-page/Iframe-PlotlyJs.page.vue index 33eb07f..d4c021d 100644 --- a/src/pages/Page/iframe-page/Iframe-PlotlyJs.page.vue +++ b/src/pages/Page/iframe-page/Iframe-PlotlyJs.page.vue @@ -3,13 +3,18 @@ import 频谱图数据 from './_频谱图_fftSize65536_32768条.json'; const compRef = useTemplateRef('compRef'); -onMounted(() => { +onMounted(async () => { console.debug('[onMounted] page 加载完成'); - compRef.value!.添加数据( + await compRef.value!.添加数据( 频谱图数据, // 实际数据点为32768 65_536, // FFT大小为65536 96_000, // 采样率为96000 ); + // await compRef.value!.添加数据( + // 频谱图数据, // 实际数据点为32768 + // 65_536, // FFT大小为65536 + // 96_000, // 采样率为96000 + // ); });