Echarts架構(gòu)解析

前言

本文章主要介紹ECharts整體的架構(gòu)設計,以及源碼中關鍵的代碼部分夏漱,用于簡單對ECharts的設計以及工作概念有個簡單的入門理解豪诲,所以不會講到太深入源碼地方,幫助想了解ECharts的同學入門挂绰。

Echarts架構(gòu)圖

image-20230810152537639.png

Echart底層依賴矢量圖形庫ZRender屎篱,基于ZRender之上做了更高層次的抽象,定義出了以下三種元素:

  • Series
  • Coordinates
  • Components

整體構(gòu)成了下述的圖表:

image-20230810152613818.png

基石:ZRender

GitHub - ecomfe/zrender: A lightweight graphic library providing 2d draw for Apache ECharts

ZRender是二維繪圖引擎葵蒂,它提供Canvas交播、SVG、VML 等多種渲染方式践付∏厥浚基于這些之上定義了如下幾個概念:

  • animation 定義動畫
  • graphic 定義圖形
  • mvc 定義模式
  • 統(tǒng)一UI Event(封裝多平臺操作差異)
  • 多種渲染引擎(Canvas/SVG/WebGL)
  • 輔助工具庫等

其中最核心的是定義圖形:

image-20230810152658797.png

于是乎,你在你就可以通過簡單的幾行代碼畫圓形了

var zr = zrender.init(document.getElementById('main'));
var circle = new zrender.Circle({
    shape: {
        cx: 150,
        cy: 150,
        r: 40
    },
    style: {
        fill: 'none',
        stroke: '#F00'
    }
});
zr.add(circle);

當然這里只是畫一個圓永高,如果用canvas代碼則如下:

var canvas = document.getElementById('main1');
canvas.width = 300;
canvas.height = 300;
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.lineWidth = 1;
ctx.strokeStyle = '#F00';
ctx.arc(150, 150, 40, 0, Math.PI * 2);
ctx.closePath();
ctx.stroke();

兩者效果如下:

image-20230810152719582.png

整體來說沒太大的差別,但是你會發(fā)現(xiàn)如果不用ZRender的抽象的話隧土,你會寫一堆復雜更底層的canvas的api代碼提针。假如demo是如下的餅圖:

image-20230810152740132.png

這里面又有文字 + 扇形 + 線段等元素的圖形,如果直接用canvas次洼,那代碼量將會是爆表关贵。所以ZRender基于Canvas、SVG卖毁、WebGL這些渲染方式揖曾,自己進行了底層代碼封裝。你只知道ZRender的基本圖形以及API相關的用法亥啦,基本也能夠滿足日常圖形繪制等等相關的需求了炭剪。當然,具體代碼可以通過Github這里查看翔脱,這里拿Line作為舉例(https://github.com/ecomfe/zrender/blob/master/src/graphic/shape/Line.ts

所以奴拦,對于EChart來說,基本底座也是基于ZRender届吁,他只需要根據(jù)實際用戶傳入的Option進行Create错妖、Update,然后解析出每個圖標元素所需要的圖形疚沐,再交由ZRender渲染就可以了暂氯。大致流程如下圖:

image-20230810152834795.png

此外,ZRender還提供了統(tǒng)一的UI Event管理用于屏蔽底層差異

image-20230810152930189.png

ECharts高級的抽象:序列 & 組件 & 坐標系

image-20230810153016966.png

上述為EChart中具體的UI元素亮蛔,主要分為兩種類型:Series和Components痴施。它們的都繼承于View目錄中的Chart.ts(https://github.com/apache/echarts/blob/f3471f0a70/src/view/Chart.ts) 以及Component.ts(https://github.com/apache/echarts/blob/f3471f0a70/src/view/Component.ts) 兩個核心接口,具體職責是負責調(diào)用ZRender繪制展示以及處理用戶交互究流。

Series用于描述數(shù)據(jù)的表現(xiàn)形態(tài)辣吃,如:折線、餅圖芬探、柱狀圖等

具體源碼對應位置如下(https://github.com/apache/echarts):

image-20230810153108958.png

Components用于豐富圖表中的具體展現(xiàn)和交互形式:XYAxis神得、Legend、Title偷仿、Toolbox等

image-20230810153139479.png

當然除了Series和Component并不能去構(gòu)成一個圖表哩簿,還缺少一個具體的坐標系系統(tǒng)。Coordinates其核心的主要是把Series轉(zhuǎn)化成坐標系的點的位置炎疆,以及協(xié)同一系列的組件完成一個圖表坐標的功能卡骂。具體坐標系在ECharts源碼中如圖所示:

image-20230810153159583.png

所有的坐標系都實現(xiàn)了CoordinateSystem接口定義(https://github.com/apache/echarts/blob/master/src/coord/CoordinateSystem.ts)其中最核心的代碼為:

image-20230810153228194.png

定義了具體的Series的data部分數(shù)據(jù)怎么轉(zhuǎn)化為坐標系中的點国裳。舉個簡單的代碼例子(以下以Gird坐標系為例):

image-20230810153303158.png

然后當Model發(fā)生變化形入,觸發(fā)UI重新Layout的時候,這里則會調(diào)用掉具體的坐標系系統(tǒng)進行Series的data重新生成為點的位置缝左。具體代碼位置如下(https://github.com/apache/echarts/blob/master/src/layout/points.ts):

image-20230810153327195.png

具體Echart目前提供的Series&Components&Coordinates如下圖所示:

  • Series(MS的Excel很早對這種圖表元素類型英文定義為Series亿遂,所以圖表類型也沿用Excel的英文)
image-20230810154308333.png

其實這里的Series并不包含坐標系的概念浓若,你可以理解是數(shù)據(jù)的表達方式的結(jié)構(gòu)

  • Coordinates(坐標系:笛卡爾坐標系、極坐標系蛇数、地理坐標系等)
image-20230810153500746.png

這里的坐標系是為了把Series中的DataList轉(zhuǎn)化為坐標系上的點

  • Components(圖標組件:標題挪钓、提示框、工具欄耳舅、圖例等)
image-20230810153531140.png

這里的Components主要是為了輔助圖表用戶某些功能的組件

狀態(tài)&事件:狀態(tài)管理工作流與事件處理

當用戶通過鼠標去點擊圖標中的某個元素碌上,就會有相對應的互動。

image-20230810153601840.png

舉個例子浦徊,比如鼠標Hover到圖中的某類數(shù)據(jù)的時候馏予,其他類別的圖表需要進行淡化處理。這里可跟用戶輸入的Option不一樣盔性,每個組件其實內(nèi)部都是有自己的UI相關的狀態(tài)霞丧,所以這里圖標淡化或者是餅圖扇區(qū)變大這種UI狀態(tài)相關的操作都是由組件本身的State去控制的,最終也是通過ZRender去渲染冕香。這里有個簡單公式:

Final Option = User Option + UserData + UI State蛹尝。

其中只要任何一個項變化,都會觸發(fā)整個EChart實例進行渲染悉尾,其中:

  • UserOption可以通過 setOption去改變
  • UserData可以因為Legend點擊隱藏某一項data而改變突那,也可以因為setOption改變
  • UI State可以因為用戶進行某種UI操作改變了UI狀態(tài),比如餅圖彈出焕襟、Hover高亮折線圖等

上述所有的行為陨收,都會觸發(fā)UI的重新Layout和Render(這一點跟瀏覽器的機制很像)。具體如下圖所示:

image-20230810153633325.png

所以根據(jù)上述這種UI更新的機制鸵赖,EChart拆分出了Model和View兩個概念务漩,通過Model數(shù)據(jù)改變進而去驅(qū)動View展示。整體數(shù)據(jù)派發(fā)就是簡單且單一的數(shù)據(jù)流它褪。

image-20230810153755905.png

在源碼設計中饵骨,一般我們可以看到如下的命名規(guī)范:

Series中一般命名習慣為:

image-20230810153831992.png

Component中一般命名習慣為:

image-20230810153906544.png

以及其中每個EChart實例對應一個EcModel負責管理所有的Model狀態(tài)分發(fā),具體GlobalModel邏輯可以從源碼去了解(https://github.com/apache/echarts/blob/f3471f0a70/src/model/Global.ts)茫打。

每當用戶點擊圖標中的Series或者是Component的時候居触,都會觸發(fā)ZRender的UI事件,通過UI事件Dispatch給GlobalModel老赤,然后GlobalModel則會通知需要更新的所有關聯(lián)的組件(當然這里每個組件都做了對應的ZRender事件派發(fā)監(jiān)聽轮洋,如下代碼所示,以Pie這個組件為例)抬旺。

https://github.com/apache/echarts/blob/f3471f0a70/src/chart/pie/install.ts

image-20230810153952581.png

此處由統(tǒng)一的Action進行托管所有ZRender的事件類型弊予,動態(tài)生成監(jiān)聽函數(shù)。

https://github.com/apache/echarts/blob/f3471f0a70/src/legacy/dataSelectAction.ts

image-20230810154035323.png

這里上一張完整的EChart數(shù)據(jù)流圖:

image-20230810154121391.png

官方文檔

image-20230810161820821.png

整體小結(jié)

EChart的底層是基于ZRender的繪圖能力开财。并且在這個基礎之上汉柒,抽象了系列误褪、組件、坐標系三種基礎概念碾褂。并且在這個概念之上兽间,設計出了一套單向的數(shù)據(jù)流,用于處理用戶數(shù)據(jù)輸入以及UI組件本身狀態(tài)改變時候的更新處理正塌。

?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末嘀略,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子乓诽,更是在濱河造成了極大的恐慌屎鳍,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,539評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件问裕,死亡現(xiàn)場離奇詭異逮壁,居然都是意外死亡,警方通過查閱死者的電腦和手機粮宛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,594評論 3 396
  • 文/潘曉璐 我一進店門窥淆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巍杈,你說我怎么就攤上這事忧饭。” “怎么了筷畦?”我有些...
    開封第一講書人閱讀 165,871評論 0 356
  • 文/不壞的土叔 我叫張陵词裤,是天一觀的道長。 經(jīng)常有香客問我鳖宾,道長吼砂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,963評論 1 295
  • 正文 為了忘掉前任鼎文,我火速辦了婚禮渔肩,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘拇惋。我一直安慰自己周偎,他們只是感情好,可當我...
    茶點故事閱讀 67,984評論 6 393
  • 文/花漫 我一把揭開白布撑帖。 她就那樣靜靜地躺著蓉坎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪胡嘿。 梳的紋絲不亂的頭發(fā)上蛉艾,一...
    開封第一講書人閱讀 51,763評論 1 307
  • 那天,我揣著相機與錄音,去河邊找鬼伺通。 笑死,一個胖子當著我的面吹牛逢享,可吹牛的內(nèi)容都是我干的罐监。 我是一名探鬼主播,決...
    沈念sama閱讀 40,468評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼瞒爬,長吁一口氣:“原來是場噩夢啊……” “哼弓柱!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起侧但,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤矢空,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后禀横,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體屁药,經(jīng)...
    沈念sama閱讀 45,850評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,002評論 3 338
  • 正文 我和宋清朗相戀三年柏锄,在試婚紗的時候發(fā)現(xiàn)自己被綠了酿箭。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,144評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡趾娃,死狀恐怖缭嫡,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情抬闷,我是刑警寧澤妇蛀,帶...
    沈念sama閱讀 35,823評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站笤成,受9級特大地震影響评架,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜炕泳,卻給世界環(huán)境...
    茶點故事閱讀 41,483評論 3 331
  • 文/蒙蒙 一古程、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧喊崖,春花似錦挣磨、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,026評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽扎即。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間香缺,已是汗流浹背再菊。 一陣腳步聲響...
    開封第一講書人閱讀 33,150評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人女轿。 一個月前我還...
    沈念sama閱讀 48,415評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像壕翩,于是被迫代替她去往敵國和親蛉迹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,092評論 2 355

推薦閱讀更多精彩內(nèi)容