JS前端以輕量fabric.js實現(xiàn)示例理解canvas
緣起
最近想系統(tǒng)看下 canvas 這個東西,所以找了一個庫看看,本來打算寫一兩篇文章沉淀一下,發(fā)現(xiàn)東西有點多??,索性就拆成了系列文章,應(yīng)該有十幾章吧,目錄大概是下面這個樣子:
目前的話已經(jīng)寫了 80% 左右的草稿,接下來會每周重新梳理一篇發(fā)出來。
canvas 這個東西其實沒太多很好的資料能夠系統(tǒng)提升,大多都是 api 的教程(可以用來入門)和某些效果的實現(xiàn)(看完直呼臥槽,隔天就忘了),會有種支離破碎的感覺??,很難互相關(guān)聯(lián)起來。
我之前想學這方面的東西也很是迷茫,不知道從哪里下手,不過 fabric.js 這個庫確實能夠幫你打開 canvas 世界的大門。
如果你想往可視化這個方向靠攏,這個系列一定能夠?qū)δ阌兴鶐椭?/p>
fabric.js 初體驗
canvas 很強大,能夠讓我們創(chuàng)建一些令人驚嘆的圖形和功能,不過它僅僅是用來繪制而已,如果要進行一些交互或者改變畫布上的內(nèi)容,就是一件很麻煩的事情??。好在 fabric.js 為 canvas 提供了一個缺失的對象模型,它負責管理畫布的狀態(tài)和渲染,可以讓我們直接使用對象來操縱畫布,極大方便了開發(fā)。如果沒用過 fabric.js 的同學建議大家去官網(wǎng)看一下,體驗一下效果,這里放張動圖讓大家感受一下:
這個系列講的就是如何一步一步從頭實現(xiàn)上面的效果,麻雀雖小五臟俱全。雖然講的是 fabric.js 的實現(xiàn),但其實是 canvas 的知識,學完這個系列再去看其他 canvas 庫應(yīng)該能更加得心應(yīng)手。
好的??,顯然有同學沒有去試一下 fabric.js,所以這里我們簡單看一下它的使用方式:
// 第一步:初始化畫布 const canvas = new fabric.Canvas('canvas'); // 第二步:創(chuàng)建物體 const rect = new fabric.Rect({ top: 200, left: 100, width: 100, height: 100, fill: 'green', }); // 第三步:向畫布中添加物體,調(diào)用 add 才會繪制到畫布中 canvas.add(rect); // 第四步:讓物體動起來 rect.animate( { top: 50, left: 400, angle: 45 }, { duration: 1000, onChange: canvas.renderAll.bind(canvas) } );
只要上面少許的代碼,就能在 canvas 中畫出一個綠色矩形,并且讓它動起來,此外還默認支持三種變換操作(平移、旋轉(zhuǎn)、縮放),非常適用于一些編輯和交互類的場景。
fabric.js 的大體結(jié)構(gòu)
那 fabric.js 是個啥呢,我們引入這個庫之后可以在控制臺打印一下 fabric:
會看到 fabric(就是命名空間)下掛載這一堆東西(各種類等),我們再截個源碼的圖:
和控制臺打印的結(jié)果大體能匹配上,fabric.js 的源碼寫的還是很清楚的,幾乎每個文件都是一個類,層次分明,注釋也多(不過是英文的),通過名字你也能猜測這個類是干什么的。我們則會實現(xiàn)它的核心部分并講解一些具體思想,大概是下面這個樣子:
這里給個最終實現(xiàn)版本的效果圖:
如果你沒接觸過類似的東西,肯定會有很多困惑??,比如:
- 怎么判斷物體被點選和框選
- 變換操作怎么搞
- 動畫怎么弄
- 怎么分組
- 如何擴展
- 要啥數(shù)學知識
- ... 那就讓我們帶著問題一起學習吧??。
canvas 能干嘛?
鑒于有些同學 canvas 接觸的比較少,所以這里就簡單總結(jié)和回顧下 canvas 的一些基礎(chǔ)知識。事實上 canvas 的 api 并不多,就像 html 中的標簽,常用的就那么幾個,但你沒碰過就會總覺得它很多又不好學,其實我們只要知道它能做什么就行??:
- 它能畫圓弧、矩形、圖片、文本、線段、貝塞爾曲線、svg
- 畫的時候可以設(shè)置各種屬性,主要有線寬、填充色、描邊色 沒了,你只要記住這兩點就行,剩下的全靠想象,比如:
- 你要畫一個圓就用圓弧來畫
- 你要畫一個點就用一個很小的圓來畫
- 你要畫一個多邊形,那就用多條線段相連
- 你要畫一個很長的曲線,那就用多段貝塞爾曲線相連,或者用多段很小很小的線段以直代曲
- 你要畫個圖表,那就得一筆一筆慢慢畫,比如雷達圖就是一堆圓圈和一個多邊形組成
- 當然最好配合上圖片,這樣能讓 canvas 看起來更加多姿多彩
- ... 另外你還要知道 canvas 雖然是個標簽,但它其實就是一幅畫,畫完的東西是不可改的,只能覆蓋或者重新畫;也無狀態(tài),canvas 并不知道你畫的是啥,也不知道你鼠標點的是哪個物體,要是想稍微修改下畫布上面物體的大小或者讓物體動起來,那一定是要清除(整個或局部)畫布再重新繪制的。 然后再說幾個注意事項:
- 畫新的幾何圖形和線條之前最好都要調(diào)用一下 beginPath,不然前后兩個圖形可能會相互影響,這是個好習慣。
- save() 和 restore() 一定要配對使用,這也是個好習慣。
- 善于運用 transform 的三種變換,以后的章節(jié)會講解到。
這里簡單擴充下 save 和 restore 這個知識點,因為一開始我們可能會對這個 api 的用法比較迷茫。一般來說 canvas 上面的東西是一個一個繪制的,每個東西有自己的狀態(tài),以 lineWidth(線寬) 和 strokeStyle(描邊色) 為例子:
const canvas = document.getElementById('canvas'); const ctx = canvas.getContext('2d'); // ... 這里如果有繪制東西,用的是默認值 ctx.save(); // ---------①開始----------↓ ctx.lineWidth = 1; ctx.strokeStyle = 'red'; ctx.strokeRect(0, 0, 20, 20); ctx.save(); // ----------②開始---------↓ ctx.lineWidth = 2; ctx.strokeStyle = 'green'; ctx.strokeRect(20, 20, 20, 20); ctx.save(); // ----------③開始----------↓ ctx.lineWidth = 3; ctx.strokeStyle = 'blue'; ctx.strokeRect(40, 40, 20, 20); // ... 這里如果有繪制東西,用的是③的狀態(tài) ctx.restore(); // ---------③結(jié)束----------↑ // ... 這里如果有繪制東西,用的是②的狀態(tài) ctx.restore(); // ----------②結(jié)束---------↑ // ... 這里如果有繪制東西,用的是①的狀態(tài) ctx.restore(); // ----------①開始---------↑ // ... 這里如果有繪制東西,用的是默認值
效果大概是下面這個樣子:
你可以把 save 和 restore 當做一對花括號??,所以它們得成對出現(xiàn),每個括號里面是一種新的繪制狀態(tài),括號外面又是另一種狀態(tài)。
它的本質(zhì)是棧的結(jié)構(gòu)(就是只能尾部添加或刪除的數(shù)組),save 的時候會把當前的一堆狀態(tài)屬性保存起來(就是一個大對象),restore 的時候就是將棧頂?shù)谋4娴臓顟B(tài)拿出來置為當前的狀態(tài),看看下面這張圖應(yīng)該能比較好的理解????:
我自己覺得 canvas 的庫大體都是數(shù)據(jù)驅(qū)動視圖的一種很好體現(xiàn),我們只負責單純的修改數(shù)據(jù)(物體的各種屬性狀態(tài)值),canvas 只負責單純的繪制,兩者各司其職,互不干擾,也有點單向數(shù)據(jù)流的味道。
小結(jié)
這個章節(jié)主要簡單介紹了下 fabric.js 和 canvas,這是這個系列的第一篇文章,其它文章也在路上了,暫時先把簡版 fabric.js 的代碼鏈接放出來吧,不過目前還在整理中
以上就是JS前端以輕量fabric.js實現(xiàn)示例理解canvas的詳細內(nèi)容,更多關(guān)于JS前端輕量fabric.js canvas的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
JS觸摸屏網(wǎng)頁版仿app彈窗型滾動列表選擇器/日期選擇器
這篇文章主要介紹了觸摸屏網(wǎng)頁版仿app彈窗型滾動列表選擇器/日期選擇器的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2016-10-10微信小程序 教程之wxapp視圖容器 scroll-view
這篇文章主要介紹了微信小程序 教程之wxapp視圖容器 scroll-view的相關(guān)資料,需要的朋友可以參考下2016-10-10JavaScript中使用toLocaleString數(shù)字格式化處理詳解
這篇文章主要為大家介紹了JavaScript中使用toLocaleString數(shù)字格式化處理詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08package.json依賴環(huán)境相關(guān)屬性詳解
這篇文章主要為大家介紹了package.json依賴環(huán)境相關(guān)屬性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-09-09