簡介:在以前的項目中用過一些圖表,好比Echart、chart.js等。遂對其比較感興趣,剛好最近在看canvas相關的知識,故嘗試寫了一下可視化的渲染引擎。通過斷斷續續的開發,目前已實現了大部分基礎圖形。html
相信你們在項目開發中都或多或少的用過一些圖表,讓咱們再看一下一個簡單的圖表是什麼樣的。git
做爲全部圖形表現的媒介,Canvas類必須有一個可供圖形呈現到網頁中的元素,故初始化需傳入一個html元素來肯定圖表的渲染位置,並須要提供相應的配置來肯定畫布的大小。此外做爲繪圖的入口還須要負責繪畫的統一調度,以及對相應事件的轉發和模擬,不然做爲HTMLCanvasElement中的一個圖像到目前爲止是不能原生響應相應的事件的,事件的訂閱和派發放到下面單獨介紹。github
配置canvas
container: 畫板的容器,canvas渲染到html中的位置
width: 畫布寬度
height: 畫布高度
style: 繪畫的各類樣式,具體設置項同原生API緩存
主要方法架構
draw() 繪製圖形。
addLayer(options) 添加圖層
addShape(type, options) 添加圖形
remove(element) 移除圖形或圖層
clear() 清除全部圖層
update() 更新畫布
ide
const canvas = new ZE.Canvas('container', {
width: 800,
height: 600,
style: {
fillStyle: 'red'
}
})
複製代碼
爲了讓canvas中的元素能夠得到單獨事件響應的能力,故而須要實現了此類,它是Canvas的基類。這個類主要提供了訂閱和分發事件的方法,還會記錄每種事件都由哪些元素訂閱,從而實現事件的冒泡機制。動畫
canvas.on('test', (str) => { console.log(str) });
canvas.emit('test', '您好');
複製代碼
何爲Element?其實Layer和Shape均可以當作是一個元素,他們有許多類似之處,Layer只是包含了若干個Shape的元素,因此提取出了Element這個類,它也是整個引擎最核心的類。咱們須要在這個類完成元素的屬性設置、動畫等相關方法。ui
const ball = canvas.addShape('circle', {
attrs: {
x: 50, // 圓心x座標
y: 50, // 圓心y座標
r: 50 // 半徑
},
style: {
fillStyle: 'red'
},
zIndex: 1, // 層級 默認 0
event: { // 能夠直接再初始化時配置相應的事件
click (e) { console.log(e); }
}
});
複製代碼
Layer是繼承Element的,通過Element的封裝後須要在Layer裏面完成的事情就很少了。Layer做爲一個容器,主要固然要提供對元素的添加和刪除了,此外我的爲每個Layer設計了一個圖形的緩存,即每一個Layer都擁有一個本身的緩存畫板,當Canvas調用draw來進行繪畫時,能夠直接將緩存的圖像繪製到顯示的繪畫板中,這樣的初衷是爲了提升繪畫的效率(待驗證),但會增長內存的使用。spa
const layer = canvas.addLayer({
x: 10,
y: 20
});
layer.addShape('text', {
attrs: {
text: 'hello'
}
});
複製代碼
Shape實際上是具體圖形的基類,它只是將每一個圖形都會用到方法提取到了這個公用的地方,好比圖形樣式的設置和繪製。
繪製其實分兩個步驟:1.建立圖形路徑。2.調用畫筆繪製到畫板。Shape類只負責後者。
因爲每種圖形的實現各不相同,而且有的須要不少複雜的數學知識在此就不一一描述了,具體能夠查看源碼或者搜索查看這些基本圖形的實現方法或者另寫相應的帖子再介紹。總之每種圖形最主要作的兩件事是1:實現圖形的路徑繪製。2:判斷一個座標點是否包含在圖形內。
一個初步的渲染引擎基本就差很少了,固然每一個人對於各個類的劃分可能不盡相同,而且對於各類機制的設計也千差萬別,最後再次附上本項目的GitHub地址,歡迎你們fork。