Echarts 原始碼解讀 一:zrender原始碼分析1var zr = zrender.init(document.getElementById(‘main‘));
2021SC@SDUSC
因為Echarts是基於zrender進行實現的,所以解讀echarts原始碼前,首先要對zrender有基本的瞭解。
zrender是canvas的一個類庫,zrender是基於canvas實現的。
目錄
zrender的src資料夾
資料夾:
animation動畫相關
contain包含判斷
core核心程式碼,包含一些工具(util.js)、事件(event.js)、唯一ID(guid.js)、矩陣運算有關(matrix.js)等
dom dom事件有關
graphic 圖形有關,shape資料夾下就是各個圖形的js檔案
mixin混入模式要混入的函式
tool工具函式,包括顏色工具(color.js)、path工具(path.js)和轉換工具(transformPath.js)
vml IE中的畫筆,vml解釋
全域性檔案:
config.js配置檔案
Element.js元素檔案,作為zrender最基本的元素
Handle.js C層,控制層
Layer.js圖層管理
Painter.js V層,檢視層
Storage.js M層,資料管理層
zrender.js入口
zrender整體架構
zrender 採用MVC 封裝
M為Model資料層,V為View檢視層,C為Controller控制層:
Storage(M):Storage為zrender中的Model層,它主要進行圖形資料的增刪改查(CRUD)操作;
Painter(V):Painter為zrender中的View層,它主要對canvas元素的生命週期進行管理,渲染檢視以及控制更新等。定義了addHover、setBackgroundColor等方法;
Handler(C):Handler為zrender中的Controller層,它主要實現事件互動處理,實現完整dom事件的模擬封裝。
圖形
處於graphic資料夾下,zrender定義了一系列圖形,供外界呼叫,包括圓形、矩形、心形、扇形、多邊形、折線等,echarts通過呼叫zrender定義好的圖形,可以很便捷地完成圖表渲染。
Displayable
Displayable.js為Path、Text等的基類,繼承自Element,定義了setStyle、useStyle等方法
TEST
文字,繼承自Displayable,呼叫了helper/text.js中的renderText方法進行繪製。主要程式碼如下:
export function renderText(hostEl, ctx, text, style, rect, prevEl) {
style.rich
? renderRichText(hostEl, ctx, text, style, rect, prevEl)
: renderPlainText(hostEl, ctx, text, style, rect, prevEl);
}
文字分為富文字以及普通文字進行分別渲染,它們均通過呼叫canvas的ctx.fillText或ctx.strokeText 等api進行文字渲染,具體實現可以檢視helper/text.js檔案。
Style
圖形的樣式檔案,定義了基本的樣式屬性,以及樣式set、clone以及判斷等方法。
Path
path為圖形的基類,繼承自Displayable,定義了buildPath、getBoundingRect、setShape等方法,其包含this._style屬性即為Style物件例項。
Shape
shape檔案下存放著zrender定義的圖形檔案,擴充套件自Path。
Circle
圓形,通過呼叫Path.extend方法進行擴充套件,重寫了buildPath方法,buildPath呼叫了canvas api:ctx.arc進行圓形的繪製,主要實現程式碼如下:
buildPath: function (ctx, shape, inBundle) {
if (inBundle) {
ctx.moveTo(shape.cx + shape.r, shape.cy);
}
ctx.arc(shape.cx, shape.cy, shape.r, 0, Math.PI * 2, true);
}
入口(zrender.js)
初始化
init呼叫:
var zr = zrender.init(document.getElementById('main'));
原始碼:進入init方法,A、初始化Zrender,B、將其存入Zrender例項map索引
zrender初始化,不讓外部直接new是為了提供全域性可控同時減少全域性汙染、降低命名衝突的風險
var instances = {}; // ZRender例項map索引
var zrender = {};
zrender.init = function(dom, opts) {
var zr = new ZRender(guid(), dom, opts);
instances[zr.id] = zr;
return zr;
};
建構函式
可以在建構函式中,看到MVC的管理機制
// zrender.js
/**
* ZRender介面類,對外可用的所有介面都在這裡!!
* storage(M)、painter(V)、handler(C)為內部私有類,外部介面不可見
* 非get介面統一返回支援鏈式呼叫~
*
* @param {string} id 唯一標識
* @param {HTMLElement} dom dom物件,不幫你做document.getElementById
*
* @return {ZRender} ZRender例項
*/
function ZRender(id, dom) {
this.id = id;
this.env = require('./tool/env'); // 瀏覽器環境識別用
this.storage = new Storage(); //shape資料CURD管理
this.painter = new Painter(dom, this.storage); //canvase元素生命週期管理,檢視渲染,繪畫,更新控制
this.handler = new Handler(dom, this.storage, this.painter);//事件互動處理,實現完整dom事件模擬封裝
// 動畫控制
this.animatingShapes = [];
this.animation = new Animation({
stage : {
update : getAnimationUpdater(this)
}
});
this.animation.start();
}
每次繪圖前,都清空畫布
// zrender_demo.html
zr.clear();
zrender執行清空時,清空storage後,再執行painter的clear()方法
// zrender.js
/**
* 清除當前ZRender下所有類圖的資料和顯示,clear後MVC和已繫結事件均還存在在,ZRender可用
*/
ZRender.prototype.clear = function () {
this.storage.del();
this.painter.clear();
return this;
};