基于 ECharts 實現動態圖表渲染支持10萬+數據點實時更新方案

引言

實現支持10萬+數據點實時更新的動態圖表渲染確實具有挑戰性,尤其是在性能和用戶體驗方面。以下是一些關鍵點和應用場景:

關鍵挑戰

  1. 性能優化

    • 渲染性能:大量數據點會導致瀏覽器渲染壓力大,可能引發卡頓。
    • 數據處理:實時更新需要高效的數據處理和傳輸機制。
  2. 內存管理

    • 內存占用:大量數據點會占用大量內存,需優化內存使用。
    • 垃圾回收:頻繁的數據更新可能觸發垃圾回收,影響性能。
  3. 用戶體驗

    • 響應速度:用戶期望圖表能快速響應,數據量大時需確保流暢性。
    • 交互體驗:縮放、平移等操作在大數據量下應保持流暢。

解決方案

  1. 數據聚合

    • 降采樣:通過聚合減少數據點,如取平均值或最大值。
    • 分塊加載:按需加載數據,減少初始加載壓力。
  2. Web Workers

    • 后臺處理:使用Web Workers在后臺處理數據,避免阻塞主線程。
  3. Canvas vs SVG

    • Canvas:適合大數據量,渲染性能較好。
    • SVG:適合交互復雜但數據量較小的場景。
   // 使用 Canvas 渲染(默認)
const chart = echarts.init(document.getElementById('chart'), null, { renderer: 'canvas' });// 使用 SVG 渲染
const chart = echarts.init(document.getElementById('chart'), null, { renderer: 'svg' });
  1. GPU加速
    • WebGL:利用WebGL進行GPU加速渲染,提升性能。

應用場景

  1. 金融領域

    • 股票市場:實時顯示大量股票數據。
    • 交易監控:監控高頻交易數據。
  2. 物聯網

    • 傳感器數據:實時顯示大量傳感器數據。
    • 設備監控:監控設備狀態和數據。
  3. 科學計算

    • 實驗數據:實時顯示實驗數據。
    • 模擬結果:顯示大規模模擬結果。
  4. 網絡監控

    • 流量監控:實時顯示網絡流量數據。
    • 安全監控:監控網絡安全事件。

示例代碼

以下是一個簡單的ECharts折線圖示例,展示如何實現動態更新:

<!DOCTYPE html>
<html>
<head><title>ECharts Dynamic Chart</title><script src="https://cdn.jsdelivr.net/npm/echarts@5.3.2/dist/echarts.min.js"></script>
</head>
<body><div id="chart" style="width: 100%; height: 600px;"></div><script>const chartDom = document.getElementById('chart');const myChart = echarts.init(chartDom);let data = [];let now = new Date();const option = {title: { text: 'Dynamic Data' },tooltip: { trigger: 'axis' },xAxis: { type: 'time' },yAxis: { type: 'value' },series: [{ name: 'Data', type: 'line', data: data }]};myChart.setOption(option);setInterval(() => {const randomValue = Math.random() * 1000;now = new Date(+now + 1000);data.push({ name: now.toString(), value: [now, randomValue] });if (data.length > 100000) {data.shift();}myChart.setOption({ series: [{ data: data }] });}, 1000);</script>
</body>
</html>

具體實現

在 ECharts 中,使用 LTTB 算法(Largest Triangle Three Buckets)和 Web Workers 是兩種常見的大數據量優化技術。下面我會詳細解釋這兩種技術的原理,具體的優化案例如下。


1. LTTB 算法(降采樣)

LTTB 是一種用于時間序列數據降采樣的算法,能夠在保留數據趨勢的同時,顯著減少數據點的數量。

原理
  • LTTB 通過將數據分成多個桶(buckets),然后從每個桶中選擇一個最具代表性的點(通常是三角形的面積最大的點)。
  • 這種方法能夠在減少數據量的同時,保留數據的關鍵特征(如峰值、谷值)。
適用場景
  • 數據量非常大(如 10萬+ 數據點)。
  • 需要保留數據的整體趨勢,而不需要每個細節。
實現步驟
  1. 將原始數據分成固定數量的桶。
  2. 對每個桶,計算三角形面積,選擇面積最大的點作為代表點。
  3. 將選出的點作為降采樣后的數據。
代碼示例
function lttb(data, threshold) {const dataLength = data.length;if (threshold >= dataLength || threshold === 0) {return data; // 無需降采樣}const sampledData = [];const bucketSize = (dataLength - 2) / (threshold - 2); // 每個桶的大小let a = 0; // 初始點let maxAreaPoint;let maxArea;let area;sampledData.push(data[a]); // 保留第一個點for (let i = 0; i < threshold - 2; i++) {let avgX = 0;let avgY = 0;let start = Math.floor((i + 1) * bucketSize) + 1;let end = Math.floor((i + 2) * bucketSize) + 1;end = end < dataLength ? end : dataLength;for (let j = start; j < end; j++) {avgX += data[j][0];avgY += data[j][1];}avgX /= (end - start);avgY /= (end - start);let pointA = data[a];maxArea = area = -1;for (let j = start; j < end; j++) {area = Math.abs((pointA[0] - avgX) * (data[j][1] - pointA[1]) -(pointA[0] - data[j][0]) * (avgY - pointA[1])) / 2;if (area > maxArea) {maxArea = area;maxAreaPoint = data[j];}}sampledData.push(maxAreaPoint);a = data.indexOf(maxAreaPoint);}sampledData.push(data[dataLength - 1]); // 保留最后一個點return sampledData;
}// 示例數據
const rawData = [];
for (let i = 0; i < 100000; i++) {rawData.push([i, Math.sin(i / 1000) * 1000]); // 10萬條數據
}// 降采樣到 1000 個點
const sampledData = lttb(rawData, 1000);
優化效果
  • 數據量從 10萬+ 減少到 1000 個點。
  • 渲染性能顯著提升,同時保留了數據的整體趨勢。

2. Web Workers(多線程處理)

Web Workers 是一種瀏覽器提供的多線程技術,可以在后臺線程中處理數據,避免阻塞主線程,從而提升頁面響應速度。

適用場景
  • 數據處理任務較重(如降采樣、數據過濾、復雜計算)。
  • 需要實時更新圖表(如每秒更新一次)。
實現步驟
  1. 創建一個 Web Worker 腳本,用于處理數據。
  2. 在主線程中,將數據發送到 Web Worker。
  3. Web Worker 處理完數據后,將結果返回給主線程。
  4. 主線程更新圖表。
代碼示例
  • Web Worker 腳本(worker.js)
    self.addEventListener('message', (event) => {const { data, threshold } = event.data;const sampledData = lttb(data, threshold); // 使用 LTTB 算法降采樣self.postMessage(sampledData); // 將結果返回主線程
    });function lttb(data, threshold) {// LTTB 算法實現(同上)
    }
    

self介紹

self 是 Web Workers 中的一個全局對象,代表 Worker 線程本身。在 Web Workers 的上下文中,self 類似于瀏覽器主線程中的 window 對象,但它指向的是 Worker 的全局作用域。


1. self 的作用

  • 在 Web Workers 中,self 用于訪問 Worker 線程的全局作用域。
  • 通過 self,可以監聽消息、發送消息、加載腳本等。

2. self 的常用方法

  • self.addEventListener:監聽事件(如 message 事件)。
  • self.postMessage:向主線程發送消息。
  • self.importScripts:加載外部腳本。
  • self.close:關閉 Worker 線程。

3. selfthis 的區別

  • 在 Web Workers 中,selfthis 通常指向同一個對象(即 Worker 線程的全局作用域)。
  • 但在某些情況下(如箭頭函數中),this 的行為可能會發生變化,因此推薦使用 self

4. 代碼示例

以下是一個簡單的 Web Worker 示例,展示了 self 的用法:

主線程代碼
// 創建 Worker
const worker = new Worker('worker.js');// 向 Worker 發送消息
worker.postMessage({ data: 'Hello from main thread!' });// 監聽 Worker 返回的消息
worker.addEventListener('message', (event) => {console.log('Received from worker:', event.data);
});
Worker 線程代碼(worker.js)
// 監聽主線程發送的消息
self.addEventListener('message', (event) => {console.log('Received from main thread:', event.data);// 向主線程發送消息self.postMessage('Hello from worker thread!');
});

5. self 的其他用途

  • 加載外部腳本

    self.importScripts('script1.js', 'script2.js');
    
  • 關閉 Worker

    self.close(); // 關閉 Worker 線程
    

6. 總結

  • self 是 Web Workers 中的全局對象,代表 Worker 線程本身。
  • 通過 self,可以監聽消息、發送消息、加載腳本等。
  • 在 Worker 中,推薦使用 self 而不是 this,以確保代碼的清晰性和一致性。

如果你在項目中使用 Web Workers,理解 self 的作用和用法是非常重要的!

  • 主線程代碼
    const worker = new Worker('worker.js');// 發送數據到 Web Worker
    worker.postMessage({ data: rawData, threshold: 1000 });// 接收處理后的數據
    worker.addEventListener('message', (event) => {const sampledData = event.data;myChart.setOption({series: [{ data: sampledData }]});
    });
    
優化效果
  • 數據處理在后臺線程中完成,主線程不會被阻塞。
  • 頁面響應速度更快,用戶體驗更流暢。

7. 完整優化案例

結合 LTTB 算法和 Web Workers,一個完整的優化案例:

場景
  • 10萬+ 數據點實時更新(每秒更新一次)。
  • 需要保留數據趨勢,同時確保頁面流暢。
實現步驟
  1. 使用 Web Workers 在后臺線程中對數據進行降采樣。
  2. 主線程接收降采樣后的數據,并更新圖表。
  3. 使用 Canvas 渲染模式,確保高性能。
代碼
<!DOCTYPE html>
<html>
<head><title>ECharts 優化案例</title><script src="https://cdn.jsdelivr.net/npm/echarts@5.3.2/dist/echarts.min.js"></script>
</head>
<body><div id="chart" style="width: 100%; height: 600px;"></div><script>const chartDom = document.getElementById('chart');const myChart = echarts.init(chartDom, null, { renderer: 'canvas' });// 初始數據let rawData = [];for (let i = 0; i < 100000; i++) {rawData.push([i, Math.sin(i / 1000) * 1000]);}// 配置 Web Workerconst worker = new Worker('worker.js');worker.postMessage({ data: rawData, threshold: 1000 });worker.addEventListener('message', (event) => {const sampledData = event.data;myChart.setOption({series: [{ data: sampledData }]});});// 實時更新數據setInterval(() => {rawData.shift(); // 移除第一個點rawData.push([rawData.length, Math.sin(rawData.length / 1000) * 1000]); // 添加新點worker.postMessage({ data: rawData, threshold: 1000 });}, 1000);</script>
</body>
</html>
優化效果
  • 數據量從 10萬+ 減少到 1000 個點。
  • 數據處理在后臺線程中完成,主線程流暢。
  • 圖表每秒更新一次,用戶體驗良好。

8. 總結

  • LTTB 算法:用于降采樣,減少數據量,同時保留數據趨勢。
  • Web Workers:用于多線程處理數據,避免阻塞主線程。
  • 結合使用:在實時更新和大數據量場景下,顯著提升性能和用戶體驗。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/898830.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/898830.shtml
英文地址,請注明出處:http://en.pswp.cn/news/898830.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

裝飾器模式 (Decorator Pattern)

裝飾器模式 (Decorator Pattern) 是一種結構型設計模式,它動態地給一個對象添加一些額外的職責,就增加功能來說,裝飾器模式相比生成子類更為靈活。 一、基礎 1 意圖 動態地給一個對象添加一些額外的職責。 就增加功能來說,裝飾器模式相比生成子類更為靈活。 2 適用場景 當…

【Java】TCP網絡編程:從可靠傳輸到Socket實戰

活動發起人小虛竹 想對你說&#xff1a; 這是一個以寫作博客為目的的創作活動&#xff0c;旨在鼓勵大學生博主們挖掘自己的創作潛能&#xff0c;展現自己的寫作才華。如果你是一位熱愛寫作的、想要展現自己創作才華的小伙伴&#xff0c;那么&#xff0c;快來參加吧&#xff01…

藍橋杯C++基礎算法-0-1背包

這段代碼實現了一個經典的0-1 背包問題的動態規劃解法。0-1 背包問題是指給定一組物品&#xff0c;每個物品有其體積和價值&#xff0c;要求在不超過背包容量的情況下&#xff0c;選擇物品使得總價值最大。以下是代碼的詳細思路解析&#xff1a; 1. 問題背景 給定 n 個物品&am…

html5炫酷的科技感3D文字效果實現詳解

炫酷的科技感3D文字效果實現詳解 這里寫目錄標題 炫酷的科技感3D文字效果實現詳解項目概述核心技術實現1. 3D文字效果2. 故障藝術效果&#xff08;Glitch Effect&#xff09;3. 動態網格背景4. 掃描線效果5. 粒子效果 性能優化考慮技術難點與解決方案項目總結擴展優化方向 項目…

車道保持中車道線識別

需要讓小車保持車道行駛&#xff0c;首先需要進行車道線識別。 也可參看論文&#xff08;上傳到資源里&#xff09;&#xff1a;自動駕駛汽車車道檢測與預測的技術解析-基于圖像處理和Hough變換的方法 1 車道識別流程 想進行車道線識別&#xff0c;并且希望在圖像中選擇一個特…

英偉達有哪些支持AI繪畫的 工程

英偉達在AI繪畫領域布局廣泛&#xff0c;其自研工具與第三方合作項目共同構建了完整的技術生態。以下是其核心支持AI繪畫的工程及合作項目的詳細介紹&#xff1a; 一、英偉達自研AI繪畫工具 1. GauGAN系列 技術特點&#xff1a;基于生成對抗網絡&#xff08;GAN&#xff09;&…

驅動開發的引入

1.引入 Linux內核的整體架構本就非常龐大&#xff0c;其包含的組件也非常多。而我們怎樣把需要的部分都包含在內核中呢? 一種方法是把所有需要的功能都編譯到Linux內核中。這會導致兩個問題&#xff0c;一是生成的內核會很大&#xff0c;二是如果我們要在現有的內核中新增或刪…

AI日報 - 2025年3月24日

&#x1f31f; 今日概覽&#xff08;60秒速覽&#xff09; ▎&#x1f916; AGI突破 | Lyra生物序列建模架構效率驚人 在100生物任務中達最優&#xff0c;推理速度提升高達12萬倍 ▎&#x1f4bc; 商業動向 | OpenAI用戶破4億&#xff0c;Meta與Reliance探討AI合作 生態擴展與全…

VMware上對CentOS7虛擬機進行磁盤擴容、縮容

在VMware 17 Pro上對CentOS 7虛擬機進行磁盤擴容&#xff0c;同時保證原先部署的軟件正常使用&#xff0c;可以按照以下步驟進行操作&#xff1a; 一、擴容 步驟一&#xff1a;關閉虛擬機并在VMware中擴展磁盤容量 關閉虛擬機&#xff1a;在VMware Workstation 17 Pro中&…

.gitignore使用指南

.gitignore使用指南 目錄 什么是.gitignore為什么需要.gitignore如何創建.gitignore文件.gitignore文件的語法規則 忽略單個文件忽略目錄忽略特定類型的文件不忽略特定文件或目錄遞歸匹配 示例.gitignore文件注意事項更多特殊場景匹配規則 忽略多個特定后綴的文件忽略特定目錄…

OpenCV旋轉估計(3)幫助構建一個最大生成樹(Maximum Spanning Tree)函數findMaxSpanningTree()

操作系統&#xff1a;ubuntu22.04 OpenCV版本&#xff1a;OpenCV4.9 IDE:Visual Studio Code 編程語言&#xff1a;C11 算法描述 cv::detail::findMaxSpanningTree 是 OpenCV 中用于圖像拼接工作流的一個函數&#xff0c;它幫助構建一個最大生成樹&#xff08;Maximum Spanni…

Android在kts中簡單使用AIDL

Android在kts中簡單使用AIDL AIDL相信做Android都有所了解&#xff0c;跨進程通信會經常使用&#xff0c;這里就不展開講解原理跨進程通信的方式了&#xff0c;最近項目換成kts的方式&#xff0c;于是把aidl也換成了統一的方式&#xff0c;其中遇到了很多問題&#xff0c;這里…

論文閱讀:2024-NAACL Semstamp、2024-ACL (Findings) k-SemStamp

總目錄 大模型安全相關研究:https://blog.csdn.net/WhiffeYF/article/details/142132328 Semstamp: A semantic watermark with paraphrastic robustness for text generation https://aclanthology.org/2024.naacl-long.226/ k-SemStamp: A Clustering-Based Semantic Wate…

物化視圖詳解:數據庫性能優化的利器

物化視圖&#xff08;Materialized View&#xff09;作為數據庫性能優化的核心手段&#xff0c;通過預計算和存儲查詢結果&#xff0c;顯著提升了復雜查詢的效率。本文將深入剖析物化視圖的工作原理、應用場景及最佳實踐&#xff0c;幫助企業在合適的場景中充分發揮其性能優勢。…

快速入手:Nacos融合SpringCloud成為注冊配置中心

快速入手&#xff1a;Nacos融合SpringCloud成為注冊配置中心 前言安裝Nacos項目搭建添加配置啟動類添加注解運行項目服務調用RestTemplate 模式FeignClient 模式 Gateway 網關 前言 Spring Cloud是一系列框架的集合&#xff0c;提供了微服務架構下的各種解決方案&#xff0c;如…

2025年2月-3月后端go開發找工作感悟

整體感悟 目標 找工作首先要有一個目標&#xff0c;這個目標盡可能的明確&#xff0c;比如我要字節、拼多多之類的公司&#xff0c;還是要去百度、滴滴這樣的&#xff0c;或者目標是創業公司。但是這個目標是會動態調整的&#xff0c;有可能我們的心態發生了變化&#xff0c;一…

Python | 如何在Pandas中刪除常量列

在數據分析中&#xff0c;經常會遇到數據集中始終具有常量值的列&#xff08;即&#xff0c;該列中的所有行包含相同的值&#xff09;。這樣的常量列不提供有意義的信息&#xff0c;可以安全地刪除而不影響分析。 如&#xff1a; 在本文中&#xff0c;我們將探索如何使用Pyth…

5.高頻加熱的原理與常用集成電路介紹

一、高頻加熱的類型 利用高頻電源加熱通常由兩種方法&#xff1a;電介質加熱&#xff08;被加熱物體絕緣&#xff09;與感應加熱&#xff08;被加熱物體導電&#xff09;&#xff0c;詳細解釋如下&#xff1a; 電介質加熱&#xff08;利用高頻電壓的高頻電場導致物體自身分子摩…

串口通信與Modbus通信的區別和聯系

一、定義與定位 1?、串口通信? 是物理層的硬件接口標準&#xff0c;用于實現設備間的?串行數據傳輸?&#xff0c;常見類型包括RS-232、RS-485和RS-422?35。其功能是完成并行數據與串行信號的轉換&#xff0c;并定義電氣特性&#xff08;如電平、傳輸速率&#xff09;?。…

Linux生產者消費者模型

Linux生產者消費者模型 Linux生產者消費者模型詳解生產者消費者模型生產者消費者模型的概念生產者消費者模型的特點生產者消費者模型優點 基于BlockingQueue的生產者消費者模型基于阻塞隊列的生產者消費者模型模擬實現基于阻塞隊列的生產消費模型基礎實現生產者消費者步調調整條…