文章作者:萌萌噠的邱邱邱邱
原始鏈接:https://qiuruolin.github.io/2019/05/20/echarts-1/
前言
由于echarts是基于zrender進行實作的,所以要解讀echarts原始碼,首先要對zrender有大致的了解,在這篇文章中,我將對zrender的整體結構進行大致的解讀,
介紹
zrender是canvas的一個類別庫,也就是說zrender是基于canvas實作的,canvas API可以參考:W3CSchool Canvas 參考手冊
在后續的解讀中,我們會介紹zrender使用canvas api 的位置及用途,
目錄介紹
檔案夾:
- animation 影片有關;
- contain 包含判斷;
- container Group.js 元素組的概念;
- core 核心代碼,包含一些工具(util.js)、事件(event.js)、唯一ID(guid.js)、矩陣運算有關(matrix.js)等;
- dom HandleProxy.js dom事件有關;
- graphic 圖形有關,shape檔案夾下就是各個圖形的js檔案;
- mixin 混入模式要混入的函式;
- tool 工具函式,包括顏色工具(color.js),path工具(path.js)和轉換工具(transformPath.js);
- vml IE中的畫筆,[vml解釋](http://www.g168.net/txt/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等方法,
Text
文本,繼承自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);
}
Arc
弧形,通過呼叫Path.extend方法進行擴展,重寫了buildPath方法,buildPath呼叫了canvas api:ctx.arc進行弧形的繪制,主要實作代碼如下:
buildPath: function (ctx, shape) {
var x = shape.cx;
var y = shape.cy;
var r = Math.max(shape.r, 0);
var startAngle = shape.startAngle;
var endAngle = shape.endAngle;
var clockwise = shape.clockwise;
var unitX = Math.cos(startAngle);
var unitY = Math.sin(startAngle);
ctx.moveTo(unitX * r + x, unitY * r + y);
ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
}
Heart
心形??,通過呼叫Path.extend方法進行擴展,重寫了buildPath方法,buildPath呼叫了canvas api:ctx.bezierCurveTo進行弧形的繪制,主要實作代碼如下:
buildPath: function (ctx, shape) {
var x = shape.cx;
var y = shape.cy;
var a = shape.width;
var b = shape.height;
ctx.moveTo(x, y);
ctx.bezierCurveTo(
x + a / 2, y - b * 2 / 3,
x + a * 2, y + b / 3,
x, y + b
);
ctx.bezierCurveTo(
x - a * 2, y + b / 3,
x - a / 2, y - b * 2 / 3,
x, y
);
}
bezierCurveTo(控制點1x坐標, 控制點1y坐標, 控制點2x坐標, 控制點2y坐標, 結束點x坐標, 結束點y坐標)
三次被塞爾曲線繪制:
- P0為開始點,P1為控制點1,P2為控制點2,P3為結束點
- 取 P0P1 中點M
- 取 P1P2 中點M’
- 取 MM’ 中點P
- 則 P 為曲線的必經點
具體繪制圖如下:

同理,我們可以繪制出左半邊心形:

Droplet
水滴形狀💧,通過呼叫Path.extend方法進行擴展,重寫了buildPath方法,buildPath呼叫了canvas api:ctx.bezierCurveTo進行弧形的繪制,貝塞爾曲線的繪制程序同心形繪制原理,主要實作代碼如下:
buildPath: function (ctx, shape) {
var x = shape.cx;
var y = shape.cy;
var a = shape.width;
var b = shape.height;
ctx.moveTo(x, y + a);
ctx.bezierCurveTo(
x + a,
y + a,
x + a * 3 / 2,
y - a / 3,
x,
y - b
);
ctx.bezierCurveTo(
x - a * 3 / 2,
y - a / 3,
x - a,
y + a,
x,
y + a
);
ctx.closePath();
}
Ellipse
橢圓,通過呼叫Path.extend方法進行擴展,重寫了buildPath方法,buildPath呼叫了canvas api:ctx.bezierCurveTo進行弧形的繪制,貝塞爾曲線的繪制程序同心形繪制原理,主要實作代碼如下:
buildPath: function (ctx, shape) {
var k = 0.5522848;
var x = shape.cx;
var y = shape.cy;
var a = shape.rx;
var b = shape.ry;
var ox = a * k; // 水平控制點偏移量
var oy = b * k; // 垂直控制點偏移量
// 從橢圓的左端點開始順時針繪制四條三次貝塞爾曲線
ctx.moveTo(x - a, y);
ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b);
ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y);
ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b);
ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y);
ctx.closePath();
}
Sector
扇形,通過呼叫Path.extend方法進行擴展,重寫了buildPath方法,buildPath呼叫了canvas api:ctx.arc以及arc.lineTo進行圓形的繪制,主要實作代碼如下:
buildPath: function (ctx, shape) {
var x = shape.cx;
var y = shape.cy;
var r0 = Math.max(shape.r0 || 0, 0);
var r = Math.max(shape.r, 0);
var startAngle = shape.startAngle;
var endAngle = shape.endAngle;
var clockwise = shape.clockwise;
var unitX = Math.cos(startAngle);
var unitY = Math.sin(startAngle);
ctx.moveTo(unitX * r0 + x, unitY * r0 + y);
ctx.lineTo(unitX * r + x, unitY * r + y);
ctx.arc(x, y, r, startAngle, endAngle, !clockwise);
ctx.lineTo(
Math.cos(endAngle) * r0 + x,
Math.sin(endAngle) * r0 + y
);
if (r0 !== 0) {
ctx.arc(x, y, r0, endAngle, startAngle, clockwise);
}
ctx.closePath();
}
zrender還定義了Rect矩形、Isogon正多邊形、Line直線、Polygon多邊形、Polyline折線、Ring圓環、Rose玫瑰線、Star n角星等圖形,其實作程序基本與上述圖形上類似,都是基于canvas的lineTo、arc、bezierCurveTo等api進行繪制的,這邊就不做一一介紹了,
總結
zrender中封裝了很多工具,在后續echarts原始碼解讀中,我們可以看到echarts是基于zrender進行開發的,
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/255188.html
標籤:其他
上一篇:性能優化專題 - MySql 性能優化 - 04 - MySql調優
下一篇:細品分布式事務
