ECharts圖表工廠,完整代碼+思路邏輯

Echart工廠支持柱狀圖(bar)折線圖(line)散點圖(scatter)餅圖(pie)雷達圖(radar)極坐標柱狀圖(polarBar)極坐標折線圖(polarLine)等多種圖表,及其對應擴展圖表:

git鏈接:sq/UI/src/components/Echarts at main · afigzb/sq (github.com)https://github.com/afigzb/sq/tree/main/UI/src/components/Echarts

展示頁面,后續附帶詳細的說明:?


引言

ECharts 是一個功能強大的圖表庫,廣泛應用于數據可視化場景。然而,其復雜的配置項和高學習曲線常常讓開發者望而卻步。本文將介紹一個精心設計的圖表工廠系統,通過封裝 ECharts 的復雜性,提供簡潔的 API 和統一的開發體驗,幫助開發者快速構建圖表,提高效率和代碼可維護性。本文將全面介紹其設計背景、架構、功能特性及使用方法,帶你了解如何利用它簡化圖表開發。


設計背景:為什么我要重新封裝一個圖表工廠?

見此代碼:

const option = {color: ['#5470c6', '#91cc75', '#fac858', '#ee6666'],backgroundColor: '#ffffff',xAxis: {type: 'category',data: ['A', 'B', 'C'],axisLine: { lineStyle: { color: '#cccccc' } },axisLabel: { color: '#666666' },splitLine: { lineStyle: { color: '#cccccc', opacity: 0.4 } }},yAxis: {type: 'value',axisLine: { lineStyle: { color: '#cccccc' } },axisLabel: { color: '#666666' },splitLine: { lineStyle: { color: '#cccccc', opacity: 0.4 } }},series: [{type: 'bar',data: [120, 200, 150]}],tooltip: {backgroundColor: '#333333',textStyle: { color: '#ffffff' }},grid: { left: '5%', right: '5%', bottom: '15%', top: '5%' }
};

這是一個標準的Echart?配置項,在實際開發過程中項目中往往不止一個Echart圖表,同時圖表的配置項也遠比這負責,這就導致了:

  1. 配置重復:每個圖表都需要重復設置顏色、背景、提示框等通用配置。
  2. 維護困難:修改主題或樣式時,需要逐一調整每個圖表的配置。
  3. 類型散亂:不同圖表類型的配置差異大,缺乏統一抽象。
  4. 維護成本高:ECharts 的 API 龐大,寫好的配置項難以更改。

基于這些問題,EChartFactory2 的設計目標是:

  • 簡化配置:從繁瑣的手動配置轉為簡單的數據輸入。
  • 統一接口:讓所有圖表類型共享一致的調用方式。
  • 集中管理:通過主題系統統一管理樣式,支持動態切換。
  • 易于擴展:方便添加新圖表類型和功能。

架構設計:分層抽象的思考過程

核心設計思想:分離通用與特定

為了探尋Echart圖表的設計規律我收集了項目中常見的圖表配置,進行對比分析,如下:

// 柱狀圖配置示例
const barOption = {color: ['#5470c6', '#91cc75', '#fac858'],          // 🔄 重復出現backgroundColor: '#ffffff',                         // 🔄 重復出現grid: { left: '5%', right: '5%', top: '5%', bottom: '15%' }, // 🔄 重復出現tooltip: {                                          // 🔄 重復出現backgroundColor: '#333333',textStyle: { color: '#ffffff' }},xAxis: {                                            // ? 圖表特定type: 'category',data: ['銷售', '市場', '研發'],axisLine: { lineStyle: { color: '#cccccc' } },axisLabel: { color: '#666666' }},yAxis: {                                            // ? 圖表特定  type: 'value',axisLine: { lineStyle: { color: '#cccccc' } },axisLabel: { color: '#666666' }},series: [{                                          // ? 圖表特定type: 'bar',data: [320, 280, 450]}]
};// 折線圖配置示例
const lineOption = {color: ['#5470c6', '#91cc75', '#fac858'],          // 🔄 重復出現backgroundColor: '#ffffff',                         // 🔄 重復出現grid: { left: '5%', right: '5%', top: '5%', bottom: '15%' }, // 🔄 重復出現tooltip: {                                          // 🔄 重復出現backgroundColor: '#333333',textStyle: { color: '#ffffff' }},xAxis: {                                            // ? 圖表特定(和柱狀圖相似)type: 'category', data: ['1月', '2月', '3月'],axisLine: { lineStyle: { color: '#cccccc' } },axisLabel: { color: '#666666' }},yAxis: {                                            // ? 圖表特定(和柱狀圖相似)type: 'value',axisLine: { lineStyle: { color: '#cccccc' } },axisLabel: { color: '#666666' }},series: [{                                          // ? 圖表特定(配置差異大)type: 'line',data: [820, 932, 901],smooth: true,symbol: 'circle'}]
};// 餅圖配置示例
const pieOption = {color: ['#5470c6', '#91cc75', '#fac858'],          // 🔄 重復出現backgroundColor: '#ffffff',                         // 🔄 重復出現  tooltip: {                                          // 🔄 重復出現backgroundColor: '#333333',textStyle: { color: '#ffffff' }},// ? 注意:餅圖沒有 xAxis、yAxis、gridseries: [{                                          // ? 圖表特定(完全不同)type: 'pie',radius: '50%',data: [{ value: 1048, name: '搜索引擎' },{ value: 735, name: '直接訪問' },{ value: 580, name: '郵件營銷' }]}]
};// 雷達圖配置示例:
const radarOption = {color: ['#5470c6', '#91cc75', '#fac858'],          // 🔄 重復出現backgroundColor: '#ffffff',                         // 🔄 重復出現tooltip: {                                          // 🔄 重復出現backgroundColor: '#333333',textStyle: { color: '#ffffff' }},// ? 注意:雷達圖沒有 xAxis、yAxis、gridradar: {                                            // ? 圖表特定(獨有的坐標系)indicator: [{ name: '銷售', max: 100 },{ name: '管理', max: 100 },{ name: '技術', max: 100 }]},series: [{                                          // ? 圖表特定(又是不同的結構)type: 'radar',data: [{value: [60, 73, 85],name: '預算分配'}]}]
};

通過對比分析,我們可以發現這些圖標基本可以劃分成以下幾部分:

// 通用配置(所有圖表都需要,配置內容基本相同)
const universalConfig = {color: [],           // 調色板 - 所有圖表都需要backgroundColor: '', // 背景色 - 所有圖表都需要tooltip: {},        // 提示框 - 所有圖表都需要,但觸發方式可能不同legend: {},         // 圖例 - 大部分圖表需要toolbox: {}         // 工具箱 - 看項目需求,但配置方式變化很小
};// 特定配置(每種圖表獨有,配置內容差異很大)
const specificConfig = {// 直角坐標系圖表(柱狀圖、折線圖、散點圖)xAxis: {},          // X軸配置yAxis: {},          // Y軸配置  grid: {},           // 網格配置// 極坐標圖表polar: {},          // 極坐標配置angleAxis: {},      // 角度軸radiusAxis: {},     // 徑向軸// 雷達圖radar: {},          // 雷達圖配置(帶指示器)// 所有圖表都有,但配置差異巨大series: []          // 系列配置(每種圖表類型完全不同)
};

如果能自動生成通用配置,只讓用戶關心數據和特定需求,Echart代碼將得到極大程度的簡化。

配置映射系統的設計

有了這個思路后,我開始思考:如果每種圖表類型都有一個"配置生成器",那么我只需要告訴它圖表類型和數據,它就能自動生成完整的配置。

最初的想法很簡單,只要吧需要配置的東西單獨抽象出來統一配置不就可以了:

const CHART_TYPE_CONFIGS = {bar: {series: (data) => ({ type: 'bar', data: data.data })},line: {series: (data) => ({ type: 'line', data: data.data })}// ...
};

但很快我就發現問題了——不同圖表需要的坐標系完全不同!

第一個難題:坐標系的差異

當我試圖處理餅圖時,發現它根本不需要?xAxis 和 yAxis,而雷達圖需要的是?radar 配置。如果還是用傳統思路,我又要寫很多?if-else:

// 這樣寫太丑了...
if (chartType === 'pie') {// 不要坐標軸
} else if (chartType === 'radar') {// 要雷達配置
} else {// 要直角坐標系
}

這時我意識到,坐標系才是圖表的核心差異。于是我重新整理思路:

| 坐標系類型 | 適用圖表?| 需要的配置?|

|-----------|---------|-----------|

| 直角坐標系?(cartesian) |?柱狀圖、折線圖、散點圖 | xAxis + yAxis?+ grid |

| 極坐標系?(polar) |?極坐標柱狀圖、極坐標折線圖 | polar?+ angleAxis + radiusAxis?|

|?雷達坐標系?(radar) |?雷達圖?| radar?(帶indicator) |

|?無坐標系?(none) |?餅圖 |?隱藏所有坐標軸 |

這樣一來,我的配置映射就變成了兩層結構:

const CHART_TYPE_CONFIGS = {bar: {coordinateSystem: 'cartesian',  // 👈 指定用哪種坐標系series: (data, theme, config) => ({ /* 系列配置 */ })},pie: {coordinateSystem: 'none',       // 👈 餅圖不需要坐標系series: (data, theme, config) => ({ /* 系列配置 */ })}
};

第二個難題:主題樣式的統一

有了坐標系分類,我又遇到新問題:每次創建圖表都要設置顏色、背景色、字體等樣式,這些重復工作能否自動化?

我回顧了之前寫的圖表,發現比較常見的是幾種風格:

  • 默認風格:白底黑字,全給Echart自動化
  • 科技風格:黑底彩色,大屏常用
  • 簡約風格:淺色背景,較為正式

與其每次都手寫這些樣式,不如做成主題系統:

const themes = {default: {colors: {series: ['#5470c6', '#91cc75', '#fac858'],background: { chart: '#ffffff', tooltip: '#333333' },text: { primary: '#333333', secondary: '#666666' }}},futuristic: {colors: {series: ['#00d4ff', '#ff6b9d', '#7fff00'],background: { chart: '#0a0a0a', tooltip: 'rgba(0,0,0,0.8)' },text: { primary: '#ffffff', secondary: '#cccccc' }}}
};

這樣我們就能一鍵切換整個圖表的視覺風格了。

第三個難題:如何合并配置?

現在有了圖表類型配置、坐標系配置、主題配置,但我們的邏輯是把Echart拆解成一個個獨立部分,最終要合并在一起才是我們需要的ECharts 配置

顯然簡單的?Object.assign?不可行,因為Echarts配置是多層嵌套的:

const config1 = { series: [{ itemStyle: { color: 'red' } }] };
const config2 = { series: [{ itemStyle: { borderWidth: 2 } }] };// Object.assign 會直接覆蓋,丟失 color 配置
Object.assign(config1, config2); 
// 結果:{ series: [{ itemStyle: { borderWidth: 2 } }] } ?// 我需要的是深度合并
// 結果:{ series: [{ itemStyle: { color: 'red', borderWidth: 2 } }] } ?

所以我寫了一個深度合并函數,確保所有配置都能正確合并。

整合:EChartFactory2?的誕生

有了這些基礎設施,我開始設計核心的工廠類。我的設計原則是:

  1. 使用簡單:簡單調用函數就能創建
  1. 配置靈活:支持自定義配置覆蓋默認值
  1. 功能完整:支持主題切換、類型切換、動態更新

于是有了這樣的 API:

// 創建圖表
const factory = new EChartFactory2(container, 'bar', 'default');// 更新數據
factory.update({xAxis: ['產品A', '產品B', '產品C'],series: { data: [120, 200, 150] }
});// 切換主題
factory.switchTheme('futuristic');// 切換類型
factory.switchType('line');

實際效果:還算讓人滿意

我們做一個簡單的對比,假設用戶的需求是:

創建一個銷售數據的柱狀圖,要求科技風格,支持堆疊顯示。

傳統寫法:

const option = {color: ['#00d4ff', '#ff6b9d', '#7fff00', '#ffaa00'],backgroundColor: '#0a0a0a',grid: {left: '3%', right: '4%', bottom: '3%', top: '4%',containLabel: true,borderColor: '#333333'},tooltip: {trigger: 'axis',backgroundColor: 'rgba(0, 0, 0, 0.8)',borderColor: '#00d4ff',borderWidth: 1,textStyle: { color: '#ffffff', fontSize: 12 },axisPointer: {type: 'shadow',shadowStyle: { color: 'rgba(0, 212, 255, 0.2)' }}},legend: {textStyle: { color: '#ffffff' },icon: 'rect',itemHeight: 8,itemGap: 20},xAxis: {type: 'category',data: ['1月', '2月', '3月', '4月'],axisLine: { lineStyle: { color: '#333333', width: 1 } },axisLabel: { color: '#cccccc', fontSize: 11 },splitLine: { show: false }},yAxis: {type: 'value',axisLine: { lineStyle: { color: '#333333', width: 1 } },axisLabel: { color: '#cccccc', fontSize: 11 },splitLine: {lineStyle: { color: '#333333', width: 0.5, opacity: 0.6 }}},series: [{name: '銷售額',type: 'bar',stack: 'total',data: [120, 132, 101, 134],itemStyle: {color: '#00d4ff',borderRadius: [2, 2, 0, 0]}},{name: '利潤',type: 'bar', stack: 'total',data: [220, 182, 191, 234],itemStyle: {color: '#ff6b9d',borderRadius: [2, 2, 0, 0]}}]
};const chart = echarts.init(document.getElementById('chart'));
chart.setOption(option);

用工廠后:

const chart = createChart(document.getElementById('chart'), 'bar', 'futuristic');
chart.update({xAxis: ['1月', '2月', '3月', '4月'],series: [{ name: '銷售額', data: [120, 132, 101, 134] },{ name: '利潤', data: [220, 182, 191, 234] }]
}, { stack: 'total' });

代碼量從?60 行減少到 5?行,減少了?92%!

更重要的是,假設現在客戶說"把這個圖改成折線圖",我只需要把代碼中的bar改成line即可:

const chart = createChart(document.getElementById('chart'), 'line', 'futuristic');
chart.update({xAxis: ['1月', '2月', '3月', '4月'],series: [{ name: '銷售額', data: [120, 132, 101, 134] },{ name: '利潤', data: [220, 182, 191, 234] }]
}, { stack: 'total' });

而且越復雜的配置,我這邊修改起來就越簡單,越統一。

詳細代碼可以從git中獲取:

sq/UI/src/components/Echarts at main · afigzb/sq (github.com)https://github.com/afigzb/sq/tree/main/UI/src/components/Echarts

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

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

相關文章

如何制作令人印象深刻的UI設計?

1. 規劃用戶旅程 規劃用戶旅程是創建高效且吸引人的UI設計的第一步。設計師需要深入了解目標用戶群體的需求和行為模式,這通常涉及用戶調研、創建用戶角色(Personas)和繪制用戶旅程圖(User Journey Maps)。通過這種方…

k8s 離線安裝 kube-prometheus-stack

配置共享存儲 Prometheus 需要配置持久化存儲,防止數據丟失 服務端 服務端安裝 NFS 服務 sudo apt install nfs-kernel-server 創建共享目錄,在服務器端創建 /nfs 目錄。 mkdir /nfs chmod -R 777 /nfs # 設置文件權限 nfs目錄下只給了默認權限&#xff…

ceph osd 磁盤分區對齊

分區對齊可以提高讀寫速度的原理是什么 分區對齊可以提高磁盤讀寫速度的原理主要在于 磁盤的物理扇區大小與操作系統發起的讀寫請求之間是否對齊。如果不對齊,每次讀寫操作可能會跨越多個物理扇區,造成額外的 I/O 操作,從而降低性能。 ?? 原理詳解 1. 物理扇區(Physica…

Simon J.D. Prince《Understanding Deep Learning》

學習神經網絡和深度學習推薦這本書,這本書站位非常高,且很多問題都深入剖析了,甩其他同類書籍幾條街。 多數書,不深度分析、沒有知識體系,知識點零散、章節之間孤立。還有一些人Tian所謂的權威,醒醒吧。 …

【泛微系統】后端開發Action常用方法

后端開發Action常用方法 代碼實例經驗分享:代碼實例 經驗分享: 本文分享了后端開發中處理工作流Action的常用方法,主要包含以下內容:1) 獲取工作流基礎信息,如流程ID、節點ID、表單ID等;2) 操作請求信息,包括請求緊急程度、操作類型、用戶信息等;3) 表單數據處理,展示…

SSH的screen方法

創建一個screen窗口,(在需要運行程序的文件夾內)使用 screen -S name 命令,其中 name 是窗口的名字。 在窗口中執行需要的命令。 當需要臨時離開時,使用快捷鍵 ctrlA D 回來時,使用 screen -r name 恢復…

無法訪問org.springframework.boot.SpringApplication

無法訪問org.springframework.boot.SpringApplication 檢查springboot和jdk的版本是否適配檢查jdk的設置是否統一 主要檢查下面幾處地方

洛谷 P1800 software(DP+二分)【提高+/省選?】

題目鏈接 https://www.luogu.com.cn/problem/P1800 思路 對于大于等于最優解的天數,一定能使公司交付軟件。對于小于最優解的天數,一定無法使公司交付軟件。所以考慮二分答案 x x x。 定義 f [ i ] [ j ] f[i][j] f[i][j]表示前 i i i個人做了 j j j…

C++性能測試工具——sysprof的使用

一、sysprof sysprof相對于前面的一些性能測試工具來說,要簡單不少。特別是其圖形界面的操作,非常容易上手,它還支持分析文件的保存和導入功能,這是一個非常不錯的功能。做為一款系統性能測試工具,它支持多種硬件平臺…

redis數據持久化和配置-15(備份和還原 Redis 數據)

備份和還原 Redis 數據 備份和恢復數據是管理任何數據庫系統(包括 Redis)的關鍵方面。數據丟失可能是由于硬件故障、軟件錯誤、意外刪除甚至惡意攻擊而發生的。因此,擁有強大的備份和恢復策略對于確保數據持久性和業務連續性至關重要。本課將…

【上位機——WPF】布局控件

布局控件 常用布局控件Panel基類Grid(網格)UniformGrid(均勻分布)StackPanel(堆積面板)WrapPanel(換行面板)DockerPanel(停靠面板)Canvas(畫布布局)Border(邊框)GridSplitter(分割窗口)常用布局控件 Grid:網格,根據自定義行和列來設置控件的布局StackPanel:棧式面板,包含的…

打卡Day33

簡單的神經網絡 數據的準備 # 仍然用4特征,3分類的鳶尾花數據集作為我們今天的數據集 from sklearn.datasets import load_iris from sklearn.model_selection import train_test_split import numpy as np# 加載鳶尾花數據集 iris load_iris() X iris.data # …

python開發環境管理和包管理

在 Python 開發中,環境管理 和 包管理 是兩個非常重要的概念。它們幫助開發者: 這里寫目錄標題 一、什么是 Python 環境管理?二、什么是 Python 包管理?三、常見文件說明(用于包管理和環境配置)四、典型流程…

Mybatis面向接口編程

添加與Mapper接口的映射 <!--UserMapper.xml--> <?xml version"1.0" encoding"UTF-8" ?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> …

GMP模型入門

go的并發實現采用的是M:N的線程模型&#xff0c;落地就是gmp模型。 M:N模型如下圖&#xff1a; gmp模型如下圖&#xff1a; --- Go 的 GMP 模型是其 高效并發調度機制的核心。GMP 代表&#xff1a; G&#xff1a;Goroutine&#xff08;用戶態線程&#xff09; M&#xff1a;…

達夢數據庫-報錯-01-[-3205]:全文索引詞庫加載出錯

目錄 一、環境信息 二、說點什么 三、模擬實驗 1、前臺啟動數據庫 2、重建全文索引報錯 3、日志信息 4、查找SYSWORD.UTF8.LIB 5、想一想加做一做 6、重啟數據庫 7、重建全文索引 8、總結 一、環境信息 名稱值CPU12th Gen Intel(R) Core(TM) i7-12700H操作系統CentO…

經典密碼學和現代密碼學的結構及其主要區別(1)維吉尼亞密碼—附py代碼

Vigenre cipher 維吉尼亞密碼 維吉尼亞密碼由布萊斯德維吉尼亞在 16 世紀發明&#xff0c;是凱撒密碼的一個更復雜的擴展。它是一種多字母替換密碼&#xff0c;使用一個關鍵字來確定明文中不同字母的多個移位值。 與凱撒密碼不同&#xff0c;凱撒密碼對所有字母都有固定的偏移…

Ubuntu部署私有Gitlab

這個東西安裝其實挺簡單的&#xff0c;但是因為我這邊遷移了數據目錄和使用自己安裝的 nginx 代理還是踩了幾個坑&#xff0c;所以大家可以注意下 先看下安裝 # 先安裝必要組件 sudo apt update sudo apt install -y curl openssh-server ca-certificates tzdata perl# 添加gi…

【JVM 02-JVM內存結構之-程序計數器】

程序計數器 筆記記錄 1. 定義2. 作用3. 特點4. 拓展理解4.1 PC寄存器存儲字節碼指令地址有什么用&#xff1f;4.2 PC寄存器為什么被設定為線程私有的&#xff1f;4.3 為什么執行native方法時&#xff0c;是undefined&#xff1f; 學習資料來源-b站黑馬JVM& 尚硅谷JVM精講與…

【node.js】數據庫與存儲

個人主頁&#xff1a;Guiat 歸屬專欄&#xff1a;node.js 文章目錄 1. 數據庫概述1.1 數據庫在Node.js中的作用1.2 Node.js支持的數據庫類型 2. 關系型數據庫集成2.1 MySQL與Node.js2.1.1 安裝MySQL驅動2.1.2 建立連接2.1.3 執行CRUD操作 2.2 PostgreSQL與Node.js2.2.1 安裝pg驅…